diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 8727436b222d..aefd865a5788 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -96,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
96 | } | 96 | } |
97 | 97 | ||
98 | wait_for_completion(&task->completion); | 98 | wait_for_completion(&task->completion); |
99 | res = -ETASK; | 99 | res = -ECOMM; |
100 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 100 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { |
101 | SAS_DPRINTK("smp task timed out or aborted\n"); | 101 | SAS_DPRINTK("smp task timed out or aborted\n"); |
102 | i->dft->lldd_abort_task(task); | 102 | i->dft->lldd_abort_task(task); |
@@ -109,6 +109,16 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | |||
109 | task->task_status.stat == SAM_GOOD) { | 109 | task->task_status.stat == SAM_GOOD) { |
110 | res = 0; | 110 | res = 0; |
111 | break; | 111 | break; |
112 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
113 | task->task_status.stat == SAS_DATA_UNDERRUN) { | ||
114 | /* no error, but return the number of bytes of | ||
115 | * underrun */ | ||
116 | res = task->task_status.residual; | ||
117 | break; | ||
118 | } if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
119 | task->task_status.stat == SAS_DATA_OVERRUN) { | ||
120 | res = -EMSGSIZE; | ||
121 | break; | ||
112 | } else { | 122 | } else { |
113 | SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " | 123 | SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " |
114 | "status 0x%x\n", __FUNCTION__, | 124 | "status 0x%x\n", __FUNCTION__, |
@@ -656,9 +666,9 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
656 | sas_ex_get_linkrate(parent, child, phy); | 666 | sas_ex_get_linkrate(parent, child, phy); |
657 | 667 | ||
658 | #ifdef CONFIG_SCSI_SAS_ATA | 668 | #ifdef CONFIG_SCSI_SAS_ATA |
659 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { | 669 | if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { |
660 | child->dev_type = SATA_DEV; | 670 | child->dev_type = SATA_DEV; |
661 | if (phy->attached_tproto & SAS_PROTO_STP) | 671 | if (phy->attached_tproto & SAS_PROTOCOL_STP) |
662 | child->tproto = phy->attached_tproto; | 672 | child->tproto = phy->attached_tproto; |
663 | if (phy->attached_sata_dev) | 673 | if (phy->attached_sata_dev) |
664 | child->tproto |= SATA_DEV; | 674 | child->tproto |= SATA_DEV; |
@@ -695,7 +705,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
695 | } | 705 | } |
696 | } else | 706 | } else |
697 | #endif | 707 | #endif |
698 | if (phy->attached_tproto & SAS_PROTO_SSP) { | 708 | if (phy->attached_tproto & SAS_PROTOCOL_SSP) { |
699 | child->dev_type = SAS_END_DEV; | 709 | child->dev_type = SAS_END_DEV; |
700 | rphy = sas_end_device_alloc(phy->port); | 710 | rphy = sas_end_device_alloc(phy->port); |
701 | /* FIXME: error handling */ | 711 | /* FIXME: error handling */ |
@@ -1896,11 +1906,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1896 | } | 1906 | } |
1897 | 1907 | ||
1898 | /* no rphy means no smp target support (ie aic94xx host) */ | 1908 | /* no rphy means no smp target support (ie aic94xx host) */ |
1899 | if (!rphy) { | 1909 | if (!rphy) |
1900 | printk("%s: can we send a smp request to a host?\n", | 1910 | return sas_smp_host_handler(shost, req, rsp); |
1901 | __FUNCTION__); | 1911 | |
1902 | return -EINVAL; | ||
1903 | } | ||
1904 | type = rphy->identify.device_type; | 1912 | type = rphy->identify.device_type; |
1905 | 1913 | ||
1906 | if (type != SAS_EDGE_EXPANDER_DEVICE && | 1914 | if (type != SAS_EDGE_EXPANDER_DEVICE && |
@@ -1926,6 +1934,15 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1926 | 1934 | ||
1927 | ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, | 1935 | ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, |
1928 | bio_data(rsp->bio), rsp->data_len); | 1936 | bio_data(rsp->bio), rsp->data_len); |
1937 | if (ret > 0) { | ||
1938 | /* positive number is the untransferred residual */ | ||
1939 | rsp->data_len = ret; | ||
1940 | req->data_len = 0; | ||
1941 | ret = 0; | ||
1942 | } else if (ret == 0) { | ||
1943 | rsp->data_len = 0; | ||
1944 | req->data_len = 0; | ||
1945 | } | ||
1929 | 1946 | ||
1930 | return ret; | 1947 | return ret; |
1931 | } | 1948 | } |