/** * 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) { struct isci_host *ihost = dev_to_ihost(task->dev); struct isci_remote_device *idev; unsigned long flags; bool io_ready; u16 tag; dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num); for_each_sas_task(num, task) { enum sci_status status = SCI_FAILURE; 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); 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); 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, SAM_STAT_TASK_ABORTED); } else { task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ status = isci_request_execute(ihost, idev, task, tag); 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); 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); } } } } 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); } return 0; }
int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { struct isci_host *ihost = dev_to_ihost(task->dev); struct isci_remote_device *idev; unsigned long flags; bool io_ready; u16 tag; dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num); for_each_sas_task(num, task) { enum sci_status status = SCI_FAILURE; 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); 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); if (!idev) { isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAS_DEVICE_UNKNOWN); } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) { isci_task_refuse(ihost, task, SAS_TASK_COMPLETE, SAS_QUEUE_FULL); } else { spin_lock_irqsave(&task->task_state_lock, flags); if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { spin_unlock_irqrestore(&task->task_state_lock, flags); isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAM_STAT_TASK_ABORTED); } else { task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); status = isci_request_execute(ihost, idev, task, tag); if (status != SCI_SUCCESS) { spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); if (test_bit(IDEV_GONE, &idev->flags)) { isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAS_DEVICE_UNKNOWN); } else { isci_task_refuse(ihost, task, SAS_TASK_COMPLETE, SAS_QUEUE_FULL); } } } } if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) { spin_lock_irqsave(&ihost->scic_lock, flags); isci_tci_free(ihost, ISCI_TAG_TCI(tag)); spin_unlock_irqrestore(&ihost->scic_lock, flags); } isci_put_device(idev); } return 0; }