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
	}
	/* add the request to the remote device request list. */
321
	list_add(&ireq->dev_node, &idev->reqs_in_process);
322

323 324 325
	/* The RNC must be unsuspended before the TMF can get a response. */
	sci_remote_device_resume(idev, NULL, NULL);

D
Dan Williams 已提交
326
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
327 328

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

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

339
	isci_print_tmf(ihost, tmf);
340 341 342 343

	if (tmf->status == SCI_SUCCESS)
		ret =  TMF_RESP_FUNC_COMPLETE;
	else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) {
D
Dan Williams 已提交
344
		dev_dbg(&ihost->pdev->dev,
345 346 347 348 349 350 351
			"%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 已提交
352
	dev_dbg(&ihost->pdev->dev,
353 354
		"%s: completed request = %p\n",
		__func__,
D
Dan Williams 已提交
355
		ireq);
356 357

	return ret;
358 359 360 361 362 363 364

 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;
365 366
}

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

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

/**
 * 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").
	 */
405
	isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset);
406 407

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

	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;
}

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

429
	spin_lock_irqsave(&ihost->scic_lock, flags);
430
	idev = isci_lookup_device(dev);
431
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
432

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

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

441
		ret = TMF_RESP_FUNC_FAILED;
442
		goto out;
443 444
	}

445 446 447
	if (dev_is_sata(dev)) {
		sas_ata_schedule_reset(dev);
		ret = TMF_RESP_FUNC_COMPLETE;
448 449 450 451 452 453 454 455 456
	} 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);
457
	}
458
 out:
459
	isci_put_device(idev);
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 487
	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)
{
488
	struct isci_host *ihost = dev_to_ihost(task->dev);
489
	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
490
	struct isci_request       *old_request = NULL;
491
	struct isci_remote_device *idev = NULL;
492 493 494
	struct isci_tmf           tmf;
	int                       ret = TMF_RESP_FUNC_FAILED;
	unsigned long             flags;
495 496 497 498 499 500

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

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

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

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

535
		ret = TMF_RESP_FUNC_COMPLETE;
536

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

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

558 559
		/* No task to send, so explicitly resume the device here */
		sci_remote_device_resume(idev, NULL, NULL);
560

561
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
562

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

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

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

590
		/* Send the task management request. */
591
		#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
592
		ret = isci_task_execute_tmf(ihost, idev, &tmf,
593
					    ISCI_ABORT_TASK_TIMEOUT_MS);
594
	}
595 596
out:
	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 721
	isci_free_tag(ihost, ireq->io_tag);
	list_del_init(&ireq->dev_node);
722

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

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

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

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

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

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

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

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

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

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

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

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