diff options
| -rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 31 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 29 | ||||
| -rw-r--r-- | include/scsi/libsas.h | 2 |
3 files changed, 34 insertions, 28 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index bad5eba4a92b..c56cc6400819 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
| @@ -37,21 +37,22 @@ | |||
| 37 | 37 | ||
| 38 | void sas_init_dev(struct domain_device *dev) | 38 | void sas_init_dev(struct domain_device *dev) |
| 39 | { | 39 | { |
| 40 | switch (dev->dev_type) { | 40 | switch (dev->dev_type) { |
| 41 | case SAS_END_DEV: | 41 | case SAS_END_DEV: |
| 42 | break; | 42 | break; |
| 43 | case EDGE_DEV: | 43 | case EDGE_DEV: |
| 44 | case FANOUT_DEV: | 44 | case FANOUT_DEV: |
| 45 | INIT_LIST_HEAD(&dev->ex_dev.children); | 45 | INIT_LIST_HEAD(&dev->ex_dev.children); |
| 46 | break; | 46 | mutex_init(&dev->ex_dev.cmd_mutex); |
| 47 | case SATA_DEV: | 47 | break; |
| 48 | case SATA_PM: | 48 | case SATA_DEV: |
| 49 | case SATA_PM_PORT: | 49 | case SATA_PM: |
| 50 | INIT_LIST_HEAD(&dev->sata_dev.children); | 50 | case SATA_PM_PORT: |
| 51 | break; | 51 | INIT_LIST_HEAD(&dev->sata_dev.children); |
| 52 | default: | 52 | break; |
| 53 | break; | 53 | default: |
| 54 | } | 54 | break; |
| 55 | } | ||
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | /* ---------- Domain device discovery ---------- */ | 58 | /* ---------- Domain device discovery ---------- */ |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index d3c1a29b8a2a..7c59f97c0287 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -72,11 +72,13 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
| 72 | struct sas_internal *i = | 72 | struct sas_internal *i = |
| 73 | to_sas_internal(dev->port->ha->core.shost->transportt); | 73 | to_sas_internal(dev->port->ha->core.shost->transportt); |
| 74 | 74 | ||
| 75 | mutex_lock(&dev->ex_dev.cmd_mutex); | ||
| 75 | for (retry = 0; retry < 3; retry++) { | 76 | for (retry = 0; retry < 3; retry++) { |
| 76 | task = sas_alloc_task(GFP_KERNEL); | 77 | task = sas_alloc_task(GFP_KERNEL); |
| 77 | if (!task) | 78 | if (!task) { |
| 78 | return -ENOMEM; | 79 | res = -ENOMEM; |
| 79 | 80 | break; | |
| 81 | } | ||
| 80 | task->dev = dev; | 82 | task->dev = dev; |
| 81 | task->task_proto = dev->tproto; | 83 | task->task_proto = dev->tproto; |
| 82 | sg_init_one(&task->smp_task.smp_req, req, req_size); | 84 | sg_init_one(&task->smp_task.smp_req, req, req_size); |
| @@ -94,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
| 94 | if (res) { | 96 | if (res) { |
| 95 | del_timer(&task->timer); | 97 | del_timer(&task->timer); |
| 96 | SAS_DPRINTK("executing SMP task failed:%d\n", res); | 98 | SAS_DPRINTK("executing SMP task failed:%d\n", res); |
| 97 | goto ex_err; | 99 | break; |
| 98 | } | 100 | } |
| 99 | 101 | ||
| 100 | wait_for_completion(&task->completion); | 102 | wait_for_completion(&task->completion); |
| @@ -104,21 +106,23 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
| 104 | i->dft->lldd_abort_task(task); | 106 | i->dft->lldd_abort_task(task); |
| 105 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | 107 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { |
| 106 | SAS_DPRINTK("SMP task aborted and not done\n"); | 108 | SAS_DPRINTK("SMP task aborted and not done\n"); |
| 107 | goto ex_err; | 109 | break; |
| 108 | } | 110 | } |
| 109 | } | 111 | } |
| 110 | if (task->task_status.resp == SAS_TASK_COMPLETE && | 112 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
| 111 | task->task_status.stat == SAM_STAT_GOOD) { | 113 | task->task_status.stat == SAM_STAT_GOOD) { |
| 112 | res = 0; | 114 | res = 0; |
| 113 | break; | 115 | break; |
| 114 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | 116 | } |
| 115 | task->task_status.stat == SAS_DATA_UNDERRUN) { | 117 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
| 118 | task->task_status.stat == SAS_DATA_UNDERRUN) { | ||
| 116 | /* no error, but return the number of bytes of | 119 | /* no error, but return the number of bytes of |
| 117 | * underrun */ | 120 | * underrun */ |
| 118 | res = task->task_status.residual; | 121 | res = task->task_status.residual; |
| 119 | break; | 122 | break; |
| 120 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | 123 | } |
| 121 | task->task_status.stat == SAS_DATA_OVERRUN) { | 124 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
| 125 | task->task_status.stat == SAS_DATA_OVERRUN) { | ||
| 122 | res = -EMSGSIZE; | 126 | res = -EMSGSIZE; |
| 123 | break; | 127 | break; |
| 124 | } else { | 128 | } else { |
| @@ -131,11 +135,10 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
| 131 | task = NULL; | 135 | task = NULL; |
| 132 | } | 136 | } |
| 133 | } | 137 | } |
| 134 | ex_err: | 138 | mutex_unlock(&dev->ex_dev.cmd_mutex); |
| 139 | |||
| 135 | BUG_ON(retry == 3 && task != NULL); | 140 | BUG_ON(retry == 3 && task != NULL); |
| 136 | if (task != NULL) { | 141 | sas_free_task(task); |
| 137 | sas_free_task(task); | ||
| 138 | } | ||
| 139 | return res; | 142 | return res; |
| 140 | } | 143 | } |
| 141 | 144 | ||
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index f388ba536128..18704a2e4f07 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
| @@ -153,6 +153,8 @@ struct expander_device { | |||
| 153 | 153 | ||
| 154 | struct ex_phy *ex_phy; | 154 | struct ex_phy *ex_phy; |
| 155 | struct sas_port *parent_port; | 155 | struct sas_port *parent_port; |
| 156 | |||
| 157 | struct mutex cmd_mutex; | ||
| 156 | }; | 158 | }; |
| 157 | 159 | ||
| 158 | /* ---------- SATA device ---------- */ | 160 | /* ---------- SATA device ---------- */ |
