task.c 23.1 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
	/* Normal notification (task_done) */
	task->task_state_flags |= SAS_TASK_STATE_DONE;
94
	task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
95 96 97 98
	task->lldd_task = NULL;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	task->task_done(task);
99
}
100

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

105 106 107 108 109 110 111 112 113

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;
}
114 115 116 117 118 119 120 121 122
/**
 * 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.
 * @gfp_flags: This parameter specifies the context of this call.
 *
 * status, zero indicates success.
 */
123
int isci_task_execute_task(struct sas_task *task, gfp_t gfp_flags)
124
{
125
	struct isci_host *ihost = dev_to_ihost(task->dev);
126
	struct isci_remote_device *idev;
127
	unsigned long flags;
128
	enum sci_status status = SCI_FAILURE;
129
	bool io_ready;
130
	u16 tag;
131

132 133 134 135 136
	spin_lock_irqsave(&ihost->scic_lock, flags);
	idev = isci_lookup_device(task->dev);
	io_ready = isci_device_io_ready(idev, task);
	tag = isci_alloc_tag(ihost);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
	dev_dbg(&ihost->pdev->dev,
		"task: %p, dev: %p idev: %p:%#lx cmd = %p\n",
		task, task->dev, idev, idev ? idev->flags : 0,
		task->uldd_task);

	if (!idev) {
		isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
				 SAS_DEVICE_UNKNOWN);
	} else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
		/* Indicate QUEUE_FULL so that the scsi midlayer
		 * retries.
		  */
		isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
				 SAS_QUEUE_FULL);
	} else {
		/* There is a device and it's ready for I/O. */
		spin_lock_irqsave(&task->task_state_lock, flags);

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

			isci_task_refuse(ihost, task,
					 SAS_TASK_UNDELIVERED,
162
					 SAS_SAM_STAT_TASK_ABORTED);
163
		} else {
164 165 166 167
			struct isci_request *ireq;

			/* do common allocation and init of request object. */
			ireq = isci_io_request_from_tag(ihost, task, tag);
168
			spin_unlock_irqrestore(&task->task_state_lock, flags);
169

170
			/* build and send the request. */
171 172
			/* do common allocation and init of request object. */
			status = isci_request_execute(ihost, idev, task, ireq);
173

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
			if (status != SCI_SUCCESS) {
				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);
194
				}
195 196
			}
		}
197
	}
198 199 200 201 202 203 204 205 206 207 208

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

	isci_put_device(idev);
209 210 211
	return 0;
}

212
static struct isci_request *isci_task_request_build(struct isci_host *ihost,
213
						    struct isci_remote_device *idev,
214
						    u16 tag, struct isci_tmf *isci_tmf)
215 216
{
	enum sci_status status = SCI_FAILURE;
217
	struct isci_request *ireq = NULL;
218
	struct domain_device *dev;
219

220
	dev_dbg(&ihost->pdev->dev,
221 222
		"%s: isci_tmf = %p\n", __func__, isci_tmf);

223
	dev = idev->domain_dev;
224 225

	/* do common allocation and init of request object. */
Dan Williams's avatar
Dan Williams committed
226
	ireq = isci_tmf_request_from_tag(ihost, isci_tmf, tag);
227 228
	if (!ireq)
		return NULL;
229 230

	/* let the core do it's construct. */
231
	status = sci_task_request_construct(ihost, idev, tag,
232
					     ireq);
233 234

	if (status != SCI_SUCCESS) {
235
		dev_warn(&ihost->pdev->dev,
236
			 "%s: sci_task_request_construct failed - "
237 238 239
			 "status = 0x%x\n",
			 __func__,
			 status);
Dan Williams's avatar
Dan Williams committed
240
		return NULL;
241 242
	}

243
	/* XXX convert to get this from task->tproto like other drivers */
244
	if (dev->dev_type == SAS_END_DEVICE) {
245
		isci_tmf->proto = SAS_PROTOCOL_SSP;
246
		sci_task_request_construct_ssp(ireq);
247 248
	}

249
	return ireq;
250 251
}

252 253 254
static int isci_task_execute_tmf(struct isci_host *ihost,
				 struct isci_remote_device *idev,
				 struct isci_tmf *tmf, unsigned long timeout_ms)
255 256
{
	DECLARE_COMPLETION_ONSTACK(completion);
257
	enum sci_status status = SCI_FAILURE;
258
	struct isci_request *ireq;
259 260
	int ret = TMF_RESP_FUNC_FAILED;
	unsigned long flags;
261
	unsigned long timeleft;
262 263 264 265 266 267 268 269
	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;
270 271 272 273

	/* sanity check, return TMF_RESP_FUNC_FAILED
	 * if the device is not there and ready.
	 */
274 275 276
	if (!idev ||
	    (!test_bit(IDEV_IO_READY, &idev->flags) &&
	     !test_bit(IDEV_IO_NCQERROR, &idev->flags))) {
277
		dev_dbg(&ihost->pdev->dev,
278
			"%s: idev = %p not ready (%#lx)\n",
279
			__func__,
280
			idev, idev ? idev->flags : 0);
281
		goto err_tci;
282
	} else
283
		dev_dbg(&ihost->pdev->dev,
284 285
			"%s: idev = %p\n",
			__func__, idev);
286 287 288

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

291
	ireq = isci_task_request_build(ihost, idev, tag, tmf);
292 293
	if (!ireq)
		goto err_tci;
294

295
	spin_lock_irqsave(&ihost->scic_lock, flags);
296 297

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

300
	if (status != SCI_SUCCESS) {
301
		dev_dbg(&ihost->pdev->dev,
302 303 304
			 "%s: start_io failed - status = 0x%x, request = %p\n",
			 __func__,
			 status,
305 306
			 ireq);
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
Dan Williams's avatar
Dan Williams committed
307
		goto err_tci;
308
	}
309
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
310

311 312 313
	/* The RNC must be unsuspended before the TMF can get a response. */
	isci_remote_device_resume_from_abort(ihost, idev);

314
	/* Wait for the TMF to complete, or a timeout. */
315
	timeleft = wait_for_completion_timeout(&completion,
316
					       msecs_to_jiffies(timeout_ms));
317 318

	if (timeleft == 0) {
319 320 321
		/* The TMF did not complete - this could be because
		 * of an unplug.  Terminate the TMF request now.
		 */
322
		isci_remote_device_suspend_terminate(ihost, idev, ireq);
323
	}
324

325
	isci_print_tmf(ihost, tmf);
326 327 328 329

	if (tmf->status == SCI_SUCCESS)
		ret =  TMF_RESP_FUNC_COMPLETE;
	else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) {
330
		dev_dbg(&ihost->pdev->dev,
331 332 333 334 335 336 337
			"%s: tmf.status == "
			"SCI_FAILURE_IO_RESPONSE_VALID\n",
			__func__);
		ret =  TMF_RESP_FUNC_COMPLETE;
	}
	/* Else - leave the default "failed" status alone. */

338
	dev_dbg(&ihost->pdev->dev,
339 340
		"%s: completed request = %p\n",
		__func__,
341
		ireq);
342 343

	return ret;
344 345 346 347 348 349 350

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

353
static void isci_task_build_tmf(struct isci_tmf *tmf,
354
				enum isci_tmf_function_codes code)
355 356
{
	memset(tmf, 0, sizeof(*tmf));
357
	tmf->tmf_code = code;
358
}
359

360 361 362
static void isci_task_build_abort_task_tmf(struct isci_tmf *tmf,
					   enum isci_tmf_function_codes code,
					   struct isci_request *old_request)
363
{
364
	isci_task_build_tmf(tmf, code);
365
	tmf->io_tag = old_request->io_tag;
366 367
}

368
/*
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
 * 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").
	 */
391
	isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset);
392 393

	#define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */
394
	ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_LU_RESET_TIMEOUT_MS);
395 396 397 398 399 400 401 402 403 404 405 406 407

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

408
int isci_task_lu_reset(struct domain_device *dev, u8 *lun)
409
{
410
	struct isci_host *ihost = dev_to_ihost(dev);
411
	struct isci_remote_device *idev;
412
	unsigned long flags;
413
	int ret = TMF_RESP_FUNC_COMPLETE;
414

415
	spin_lock_irqsave(&ihost->scic_lock, flags);
416
	idev = isci_get_device(dev->lldd_dev);
417
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
418

419
	dev_dbg(&ihost->pdev->dev,
420
		"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
421
		__func__, dev, ihost, idev);
422

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

427
		ret = TMF_RESP_FUNC_FAILED;
428
		goto out;
429 430
	}

431 432 433 434 435 436 437 438
	/* 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. */
439 440 441 442 443 444
	if (!test_bit(IDEV_GONE, &idev->flags)) {
		if (dev_is_sata(dev))
			sas_ata_schedule_reset(dev);
		else
			/* Send the task management part of the reset. */
			ret = isci_task_send_lu_reset_sas(ihost, idev, lun);
445
	}
446
 out:
447
	isci_put_device(idev);
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
	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)
{
476
	struct isci_host *ihost = dev_to_ihost(task->dev);
477
	DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
478
	struct isci_request       *old_request = NULL;
479
	struct isci_remote_device *idev = NULL;
480 481 482
	struct isci_tmf           tmf;
	int                       ret = TMF_RESP_FUNC_FAILED;
	unsigned long             flags;
483
	int                       target_done_already = 0;
484 485 486 487 488 489

	/* 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.
	 */
490
	spin_lock_irqsave(&ihost->scic_lock, flags);
491 492 493 494 495 496
	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) &&
497
	    old_request) {
498
		idev = isci_get_device(task->dev->lldd_dev);
499 500 501
		target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
					       &old_request->flags);
	}
502
	spin_unlock(&task->task_state_lock);
503
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
504

505
	dev_warn(&ihost->pdev->dev,
506 507 508
		 "%s: dev = %p (%s%s), task = %p, old_request == %p\n",
		 __func__, idev,
		 (dev_is_sata(task->dev) ? "STP/SATA"
509
					 : ((dev_is_expander(task->dev->dev_type))
510 511 512 513 514 515 516
						? "SMP"
						: "SSP")),
		 ((idev) ? ((test_bit(IDEV_GONE, &idev->flags))
			   ? " IDEV_GONE"
			   : "")
			 : " <NULL>"),
		 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
		/* 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
526
		* was successful.
527 528 529
		*/
		spin_lock_irqsave(&task->task_state_lock, flags);
		task->task_state_flags |= SAS_TASK_STATE_DONE;
530
		task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
531
		spin_unlock_irqrestore(&task->task_state_lock, flags);
532

533
		ret = TMF_RESP_FUNC_COMPLETE;
534

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

Dan Williams's avatar
Dan Williams committed
552
	if (task->task_proto == SAS_PROTOCOL_SMP ||
553
	    sas_protocol_ata(task->task_proto) ||
554
	    target_done_already ||
555
	    test_bit(IDEV_GONE, &idev->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
		dev_warn(&ihost->pdev->dev,
			 "%s: %s request"
564 565
				 " or complete_in_target (%d), "
				 "or IDEV_GONE (%d), thus no TMF\n",
566 567 568 569 570 571 572 573
			 __func__,
			 ((task->task_proto == SAS_PROTOCOL_SMP)
			  ? "SMP"
			  : (sas_protocol_ata(task->task_proto)
				? "SATA/STP"
				: "<other>")
			  ),
			 test_bit(IREQ_COMPLETE_IN_TARGET,
574 575
				  &old_request->flags),
			 test_bit(IDEV_GONE, &idev->flags));
576

577
		spin_lock_irqsave(&task->task_state_lock, flags);
578
		task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
579 580 581 582
		task->task_state_flags |= SAS_TASK_STATE_DONE;
		spin_unlock_irqrestore(&task->task_state_lock, flags);

		ret = TMF_RESP_FUNC_COMPLETE;
583
	} else {
584
		/* Fill in the tmf structure */
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
out:
596 597 598
	dev_warn(&ihost->pdev->dev,
		 "%s: Done; dev = %p, task = %p , old_request == %p\n",
		 __func__, idev, task, old_request);
599
	isci_put_device(idev);
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
	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_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.
 *
 * 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;
}

659
/*
660 661
 * isci_task_request_complete() - This function is called by the sci core when
 *    an task request completes.
662 663
 * @ihost: This parameter specifies the ISCI host object
 * @ireq: This parameter is the completed isci_request object.
664 665 666 667 668
 * @completion_status: This parameter specifies the completion status from the
 *    sci core.
 *
 * none.
 */
669 670 671 672
void
isci_task_request_complete(struct isci_host *ihost,
			   struct isci_request *ireq,
			   enum sci_task_status completion_status)
673
{
674
	struct isci_tmf *tmf = isci_request_access_tmf(ireq);
675
	struct completion *tmf_complete = NULL;
676

677
	dev_dbg(&ihost->pdev->dev,
678
		"%s: request = %p, status=%d\n",
679
		__func__, ireq, completion_status);
680

Dan Williams's avatar
Dan Williams committed
681
	set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
682

683 684 685 686
	if (tmf) {
		tmf->status = completion_status;

		if (tmf->proto == SAS_PROTOCOL_SSP) {
687 688
			memcpy(tmf->resp.rsp_buf,
			       ireq->ssp.rsp_buf,
689 690 691 692 693 694 695 696
			       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;
697
	}
698
	sci_controller_complete_io(ihost, ireq->target_device, ireq);
699
	/* set the 'terminated' flag handle to make sure it cannot be terminated
700 701
	 *  or completed again.
	 */
Dan Williams's avatar
Dan Williams committed
702
	set_bit(IREQ_TERMINATED, &ireq->flags);
703

704 705 706
	if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
		wake_up_all(&ihost->eventq);

707 708
	if (!test_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags))
		isci_free_tag(ihost, ireq->io_tag);
709

710
	/* The task management part completes last. */
711 712
	if (tmf_complete)
		complete(tmf_complete);
713 714
}

715
static int isci_reset_device(struct isci_host *ihost,
716
			     struct domain_device *dev,
717
			     struct isci_remote_device *idev)
718
{
719
	int rc = TMF_RESP_FUNC_COMPLETE, reset_stat = -1;
720 721
	struct sas_phy *phy = sas_get_local_phy(dev);
	struct isci_port *iport = dev->port->lldd_port;
722

723
	dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev);
724

725 726 727
	/* Suspend the RNC, terminate all outstanding TCs. */
	if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
	    != SCI_SUCCESS) {
728 729
		rc = TMF_RESP_FUNC_FAILED;
		goto out;
730
	}
731 732 733 734 735 736
	/* 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.
	 */
737 738 739 740 741 742 743 744 745
	if (!test_bit(IDEV_GONE, &idev->flags)) {
		if (scsi_is_sas_phy_local(phy)) {
			struct isci_phy *iphy = &ihost->phys[phy->number];

			reset_stat = isci_port_perform_hard_reset(ihost, iport,
								  iphy);
		} else
			reset_stat = sas_phy_reset(phy, !dev_is_sata(dev));
	}
746
	/* Explicitly resume the RNC here, since there was no task sent. */
747
	isci_remote_device_resume_from_abort(ihost, idev);
748

749 750
	dev_dbg(&ihost->pdev->dev, "%s: idev %p complete, reset_stat=%d.\n",
		__func__, idev, reset_stat);
751 752
 out:
	sas_put_local_phy(phy);
753 754
	return rc;
}
755

756 757 758 759 760
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;
761
	int ret;
762 763

	spin_lock_irqsave(&ihost->scic_lock, flags);
764
	idev = isci_get_device(dev->lldd_dev);
765 766
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

767 768 769 770
	if (!idev) {
		/* XXX: need to cleanup any ireqs targeting this
		 * domain_device
		 */
771
		ret = -ENODEV;
772 773
		goto out;
	}
774

775
	ret = isci_reset_device(ihost, dev, idev);
776 777 778
 out:
	isci_put_device(idev);
	return ret;
779
}