提交 1077a574 编写于 作者: D Dan Williams

isci: fix incorrect assumptions about task->dev and task->dev->port being NULL

A domain_device has the same lifetime as its related scsi_target.  The
scsi_target is reference counted based on outstanding commands,
therefore it is safe to assume that if we have a valid sas_task that the
->dev pointer is also valid.

The asd_sas_port of a domain_device has the same lifetime as the driver
so it can also never be NULL as long as the sas_task is valid and the
driver is loaded.

This also cleans up isci_task_complete_for_upper_layer(), renames it to
isci_task_refuse() and notices that the isci_completion_selection
parameter was set to isci_perform_normal_io_completion by all callers.
Signed-off-by: NDan Williams <dan.j.williams@intel.com>
上级 34cad85d
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -67,39 +67,36 @@
#include "task.h"
/**
* isci_task_complete_for_upper_layer() - This function completes the request
* to the upper layer driver in the case where an I/O needs to be completed
* back in the submit path.
* @host: This parameter is a pointer to the host on which the the request
* should be queued (either as an error or success).
* @task: This parameter is the completed request.
* @response: This parameter is the response code for the completed task.
* @status: This parameter is the status code for the completed task.
* 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.
*
* none.
*/
static void isci_task_complete_for_upper_layer(struct sas_task *task,
enum service_response response,
enum exec_status status,
enum isci_completion_selection task_notification_selection)
static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
enum service_response response,
enum exec_status status)
{
unsigned long flags = 0;
struct Scsi_Host *host = NULL;
enum isci_completion_selection disposition;
task_notification_selection
= isci_task_set_completion_status(task, response, status,
task_notification_selection);
disposition = isci_perform_normal_io_completion;
disposition = isci_task_set_completion_status(task, response, status,
disposition);
/* Tasks aborted specifically by a call to the lldd_abort_task
* function should not be completed to the host in the regular path.
*/
switch (task_notification_selection) {
* function should not be completed to the host in the regular path.
*/
switch (disposition) {
case isci_perform_normal_io_completion:
/* Normal notification (task_done) */
dev_dbg(task->dev->port->ha->dev,
dev_dbg(&ihost->pdev->dev,
"%s: Normal - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
task->lldd_task = NULL;
if (dev_is_sata(task->dev)) {
/* Since we are still in the submit path, and since
* libsas takes the host lock on behalf of SATA
......@@ -107,44 +104,36 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task,
* before we can call back and report the I/O
* submission error.
*/
if (task->dev
&& task->dev->port
&& task->dev->port->ha) {
unsigned long flags;
host = task->dev->port->ha->core.shost;
raw_local_irq_save(flags);
spin_unlock(host->host_lock);
}
raw_local_irq_save(flags);
spin_unlock(ihost->shost->host_lock);
task->task_done(task);
if (host) {
spin_lock(host->host_lock);
raw_local_irq_restore(flags);
}
spin_lock(ihost->shost->host_lock);
raw_local_irq_restore(flags);
} else
task->task_done(task);
task->lldd_task = NULL;
break;
case isci_perform_aborted_io_completion:
/* No notification because this request is already in the
* abort path.
*/
dev_warn(task->dev->port->ha->dev,
dev_warn(&ihost->pdev->dev,
"%s: Aborted - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
break;
case isci_perform_error_io_completion:
/* Use sas_task_abort */
dev_warn(task->dev->port->ha->dev,
dev_warn(&ihost->pdev->dev,
"%s: Error - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
sas_task_abort(task);
break;
default:
dev_warn(task->dev->port->ha->dev,
dev_warn(&ihost->pdev->dev,
"%s: isci task notification default case!",
__func__);
sas_task_abort(task);
......@@ -152,6 +141,10 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task,
}
}
#define for_each_sas_task(num, task) \
for (; num > 0; num--,\
task = list_entry(task->list.next, struct sas_task, list))
/**
* 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
......@@ -164,7 +157,7 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task,
*/
int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
{
struct isci_host *isci_host;
struct isci_host *ihost = task->dev->port->ha->lldd_ha;
struct isci_request *request = NULL;
struct isci_remote_device *device;
unsigned long flags;
......@@ -172,60 +165,23 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
enum sci_status status;
enum isci_status device_status;
dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num);
if ((task->dev == NULL) || (task->dev->port == NULL)) {
/* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer
* removes the target.
*/
isci_task_complete_for_upper_layer(
task,
SAS_TASK_UNDELIVERED,
SAS_DEVICE_UNKNOWN,
isci_perform_normal_io_completion
);
return 0; /* The I/O was accepted (and failed). */
}
isci_host = isci_host_from_sas_ha(task->dev->port->ha);
dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
/* Check if we have room for more tasks */
ret = isci_host_can_queue(isci_host, num);
ret = isci_host_can_queue(ihost, num);
if (ret) {
dev_warn(task->dev->port->ha->dev, "%s: queue full\n", __func__);
dev_warn(&ihost->pdev->dev, "%s: queue full\n", __func__);
return ret;
}
do {
dev_dbg(task->dev->port->ha->dev,
for_each_sas_task(num, task) {
dev_dbg(&ihost->pdev->dev,
"task = %p, num = %d; dev = %p; cmd = %p\n",
task, num, task->dev, task->uldd_task);
if ((task->dev == NULL) || (task->dev->port == NULL)) {
dev_warn(task->dev->port->ha->dev,
"%s: task %p's port or dev == NULL!\n",
__func__, task);
/* Indicate SAS_TASK_UNDELIVERED, so that the scsi
* midlayer removes the target.
*/
isci_task_complete_for_upper_layer(
task,
SAS_TASK_UNDELIVERED,
SAS_DEVICE_UNKNOWN,
isci_perform_normal_io_completion
);
/* We don't have a valid host reference, so we
* can't control the host queueing condition.
*/
goto next_task;
}
device = isci_dev_from_domain_dev(task->dev);
isci_host = isci_host_from_sas_ha(task->dev->port->ha);
if (device)
device_status = device->status;
else
......@@ -239,34 +195,28 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
if (device_status != isci_ready_for_io) {
/* Forces a retry from scsi mid layer. */
dev_warn(task->dev->port->ha->dev,
dev_warn(&ihost->pdev->dev,
"%s: task %p: isci_host->status = %d, "
"device = %p; device_status = 0x%x\n\n",
__func__,
task,
isci_host_get_state(isci_host),
isci_host_get_state(ihost),
device, device_status);
if (device_status == isci_ready) {
/* Indicate QUEUE_FULL so that the scsi midlayer
* retries.
*/
isci_task_complete_for_upper_layer(
task,
SAS_TASK_COMPLETE,
SAS_QUEUE_FULL,
isci_perform_normal_io_completion
);
isci_task_refuse(ihost, task,
SAS_TASK_COMPLETE,
SAS_QUEUE_FULL);
} else {
/* Else, the device is going down. */
isci_task_complete_for_upper_layer(
task,
SAS_TASK_UNDELIVERED,
SAS_DEVICE_UNKNOWN,
isci_perform_normal_io_completion
);
isci_task_refuse(ihost, task,
SAS_TASK_UNDELIVERED,
SAS_DEVICE_UNKNOWN);
}
isci_host_can_dequeue(isci_host, 1);
isci_host_can_dequeue(ihost, 1);
} else {
/* There is a device and it's ready for I/O. */
spin_lock_irqsave(&task->task_state_lock, flags);
......@@ -276,12 +226,9 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
spin_unlock_irqrestore(&task->task_state_lock,
flags);
isci_task_complete_for_upper_layer(
task,
SAS_TASK_UNDELIVERED,
SAM_STAT_TASK_ABORTED,
isci_perform_normal_io_completion
);
isci_task_refuse(ihost, task,
SAS_TASK_UNDELIVERED,
SAM_STAT_TASK_ABORTED);
/* The I/O was aborted. */
......@@ -290,7 +237,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
spin_unlock_irqrestore(&task->task_state_lock, flags);
/* build and send the request. */
status = isci_request_execute(isci_host, task, &request,
status = isci_request_execute(ihost, task, &request,
gfp_flags);
if (status != SCI_SUCCESS) {
......@@ -307,19 +254,14 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
* SAS_TASK_UNDELIVERED next time
* through.
*/
isci_task_complete_for_upper_layer(
task,
SAS_TASK_COMPLETE,
SAS_QUEUE_FULL,
isci_perform_normal_io_completion
);
isci_host_can_dequeue(isci_host, 1);
isci_task_refuse(ihost, task,
SAS_TASK_COMPLETE,
SAS_QUEUE_FULL);
isci_host_can_dequeue(ihost, 1);
}
}
}
next_task:
task = list_entry(task->list.next, struct sas_task, list);
} while (--num > 0);
}
return 0;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部