task.c 23.5 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
	}
D
Dan Williams 已提交
320
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
321

322 323 324
	/* The RNC must be unsuspended before the TMF can get a response. */
	isci_remote_device_resume_from_abort(ihost, idev);

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 445 446 447 448 449
	/* Suspend the RNC, kill all TCs */
	if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
	    != SCI_SUCCESS) {
		/* The suspend/terminate only fails if isci_get_device fails */
		ret = TMF_RESP_FUNC_FAILED;
		goto out;
	}
	/* All pending I/Os have been terminated and cleaned up. */
450 451 452
	if (dev_is_sata(dev)) {
		sas_ata_schedule_reset(dev);
		ret = TMF_RESP_FUNC_COMPLETE;
453 454 455
	} else {
		/* Send the task management part of the reset. */
		ret = isci_task_send_lu_reset_sas(ihost, idev, lun);
456
	}
457
 out:
458
	isci_put_device(idev);
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 485 486
	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)
{
487
	struct isci_host *ihost = dev_to_ihost(task->dev);
488
	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
489
	struct isci_request       *old_request = NULL;
490
	struct isci_remote_device *idev = NULL;
491 492 493
	struct isci_tmf           tmf;
	int                       ret = TMF_RESP_FUNC_FAILED;
	unsigned long             flags;
494 495 496 497 498 499

	/* 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.
	 */
500
	spin_lock_irqsave(&ihost->scic_lock, flags);
501 502 503 504 505 506 507 508
	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)
509
		idev = isci_get_device(task->dev->lldd_dev);
510 511

	spin_unlock(&task->task_state_lock);
512
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
513

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

518 519 520
	/* Device reset conditions signalled in task_state_flags are the
	 * responsbility of libsas to observe at the start of the error
	 * handler thread.
521
	 */
522
	if (!idev || !old_request) {
523 524 525 526 527 528 529 530 531 532
		/* 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);
533

534
		ret = TMF_RESP_FUNC_COMPLETE;
535

536 537 538
		dev_warn(&ihost->pdev->dev,
			 "%s: abort task not needed for %p\n",
			 __func__, task);
539
		goto out;
540
	}
541 542 543 544 545 546 547 548
	/* 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;
549
		goto out;
550
	}
551 552
	spin_lock_irqsave(&ihost->scic_lock, flags);

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

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

559 560 561
		/* No task to send, so explicitly resume the device here */
		isci_remote_device_resume_from_abort(ihost, idev);

562 563 564 565 566 567 568 569 570 571 572 573
		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));
574

575 576 577 578 579 580 581
		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;
582 583
	} else {
		/* Fill in the tmf stucture */
584
		isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
585
					       old_request);
586

587
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
588

589
		/* Send the task management request. */
590
		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
591
		ret = isci_task_execute_tmf(ihost, idev, &tmf,
592
					    ISCI_ABORT_TASK_TIMEOUT_MS);
593
	}
594
out:
595 596 597
	dev_warn(&ihost->pdev->dev,
		 "%s: Done; dev = %p, task = %p , old_request == %p\n",
		 __func__, idev, task, old_request);
598
	isci_put_device(idev);
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 675 676
	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;
}

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

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

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

701 702 703 704 705 706 707 708 709 710 711 712 713 714
	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;
715
	}
716
	sci_controller_complete_io(ihost, ireq->target_device, ireq);
717
	/* set the 'terminated' flag handle to make sure it cannot be terminated
718 719
	 *  or completed again.
	 */
D
Dan Williams 已提交
720
	set_bit(IREQ_TERMINATED, &ireq->flags);
721

722
	isci_free_tag(ihost, ireq->io_tag);
723

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

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

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

739 740 741
	/* Suspend the RNC, terminate all outstanding TCs. */
	if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
	    != SCI_SUCCESS) {
742 743
		rc = TMF_RESP_FUNC_FAILED;
		goto out;
744
	}
745 746 747 748 749 750
	/* 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.
	 */
751

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

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

759
	/* Explicitly resume the RNC here, since there was no task sent. */
760
	isci_remote_device_resume_from_abort(ihost, idev);
761

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

D
Dan Williams 已提交
769 770 771 772 773
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;
774
	int ret;
D
Dan Williams 已提交
775 776

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

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

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