aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libsas/Kconfig1
-rw-r--r--drivers/scsi/libsas/sas_expander.c70
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c106
-rw-r--r--drivers/scsi/libsas/sas_internal.h12
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c230
-rw-r--r--drivers/scsi/scsi_transport_sas.c118
6 files changed, 203 insertions, 334 deletions
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index 9dafe64e7c7a..13739bfacc67 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -26,6 +26,7 @@ config SCSI_SAS_LIBSAS
26 tristate "SAS Domain Transport Attributes" 26 tristate "SAS Domain Transport Attributes"
27 depends on SCSI 27 depends on SCSI
28 select SCSI_SAS_ATTRS 28 select SCSI_SAS_ATTRS
29 select BLK_DEV_BSGLIB
29 help 30 help
30 This provides transport specific helpers for SAS drivers which 31 This provides transport specific helpers for SAS drivers which
31 use the domain device construct (like the aic94xxx). 32 use the domain device construct (like the aic94xxx).
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 570b2cb2da43..6b4fd2375178 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -64,8 +64,8 @@ static void smp_task_done(struct sas_task *task)
64/* Give it some long enough timeout. In seconds. */ 64/* Give it some long enough timeout. In seconds. */
65#define SMP_TIMEOUT 10 65#define SMP_TIMEOUT 10
66 66
67static int smp_execute_task(struct domain_device *dev, void *req, int req_size, 67static int smp_execute_task_sg(struct domain_device *dev,
68 void *resp, int resp_size) 68 struct scatterlist *req, struct scatterlist *resp)
69{ 69{
70 int res, retry; 70 int res, retry;
71 struct sas_task *task = NULL; 71 struct sas_task *task = NULL;
@@ -86,8 +86,8 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
86 } 86 }
87 task->dev = dev; 87 task->dev = dev;
88 task->task_proto = dev->tproto; 88 task->task_proto = dev->tproto;
89 sg_init_one(&task->smp_task.smp_req, req, req_size); 89 task->smp_task.smp_req = *req;
90 sg_init_one(&task->smp_task.smp_resp, resp, resp_size); 90 task->smp_task.smp_resp = *resp;
91 91
92 task->task_done = smp_task_done; 92 task->task_done = smp_task_done;
93 93
@@ -151,6 +151,17 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
151 return res; 151 return res;
152} 152}
153 153
154static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
155 void *resp, int resp_size)
156{
157 struct scatterlist req_sg;
158 struct scatterlist resp_sg;
159
160 sg_init_one(&req_sg, req, req_size);
161 sg_init_one(&resp_sg, resp, resp_size);
162 return smp_execute_task_sg(dev, &req_sg, &resp_sg);
163}
164
154/* ---------- Allocations ---------- */ 165/* ---------- Allocations ---------- */
155 166
156static inline void *alloc_smp_req(int size) 167static inline void *alloc_smp_req(int size)
@@ -2130,57 +2141,50 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
2130 return res; 2141 return res;
2131} 2142}
2132 2143
2133int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, 2144void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
2134 struct request *req) 2145 struct sas_rphy *rphy)
2135{ 2146{
2136 struct domain_device *dev; 2147 struct domain_device *dev;
2137 int ret, type; 2148 unsigned int reslen = 0;
2138 struct request *rsp = req->next_rq; 2149 int ret = -EINVAL;
2139
2140 if (!rsp) {
2141 printk("%s: space for a smp response is missing\n",
2142 __func__);
2143 return -EINVAL;
2144 }
2145 2150
2146 /* no rphy means no smp target support (ie aic94xx host) */ 2151 /* no rphy means no smp target support (ie aic94xx host) */
2147 if (!rphy) 2152 if (!rphy)
2148 return sas_smp_host_handler(shost, req, rsp); 2153 return sas_smp_host_handler(job, shost);
2149
2150 type = rphy->identify.device_type;
2151 2154
2152 if (type != SAS_EDGE_EXPANDER_DEVICE && 2155 switch (rphy->identify.device_type) {
2153 type != SAS_FANOUT_EXPANDER_DEVICE) { 2156 case SAS_EDGE_EXPANDER_DEVICE:
2157 case SAS_FANOUT_EXPANDER_DEVICE:
2158 break;
2159 default:
2154 printk("%s: can we send a smp request to a device?\n", 2160 printk("%s: can we send a smp request to a device?\n",
2155 __func__); 2161 __func__);
2156 return -EINVAL; 2162 goto out;
2157 } 2163 }
2158 2164
2159 dev = sas_find_dev_by_rphy(rphy); 2165 dev = sas_find_dev_by_rphy(rphy);
2160 if (!dev) { 2166 if (!dev) {
2161 printk("%s: fail to find a domain_device?\n", __func__); 2167 printk("%s: fail to find a domain_device?\n", __func__);
2162 return -EINVAL; 2168 goto out;
2163 } 2169 }
2164 2170
2165 /* do we need to support multiple segments? */ 2171 /* do we need to support multiple segments? */
2166 if (bio_multiple_segments(req->bio) || 2172 if (job->request_payload.sg_cnt > 1 ||
2167 bio_multiple_segments(rsp->bio)) { 2173 job->reply_payload.sg_cnt > 1) {
2168 printk("%s: multiple segments req %u, rsp %u\n", 2174 printk("%s: multiple segments req %u, rsp %u\n",
2169 __func__, blk_rq_bytes(req), blk_rq_bytes(rsp)); 2175 __func__, job->request_payload.payload_len,
2170 return -EINVAL; 2176 job->reply_payload.payload_len);
2177 goto out;
2171 } 2178 }
2172 2179
2173 ret = smp_execute_task(dev, bio_data(req->bio), blk_rq_bytes(req), 2180 ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
2174 bio_data(rsp->bio), blk_rq_bytes(rsp)); 2181 job->reply_payload.sg_list);
2175 if (ret > 0) { 2182 if (ret > 0) {
2176 /* positive number is the untransferred residual */ 2183 /* positive number is the untransferred residual */
2177 scsi_req(rsp)->resid_len = ret; 2184 reslen = ret;
2178 scsi_req(req)->resid_len = 0;
2179 ret = 0; 2185 ret = 0;
2180 } else if (ret == 0) {
2181 scsi_req(rsp)->resid_len = 0;
2182 scsi_req(req)->resid_len = 0;
2183 } 2186 }
2184 2187
2185 return ret; 2188out:
2189 bsg_job_done(job, ret, reslen);
2186} 2190}
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 45cbbc44f4d7..9ead93df3a6e 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -225,47 +225,36 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
225 resp_data[2] = SMP_RESP_FUNC_ACC; 225 resp_data[2] = SMP_RESP_FUNC_ACC;
226} 226}
227 227
228int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, 228void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost)
229 struct request *rsp)
230{ 229{
231 u8 *req_data = NULL, *resp_data = NULL, *buf;
232 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); 230 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
231 u8 *req_data, *resp_data;
232 unsigned int reslen = 0;
233 int error = -EINVAL; 233 int error = -EINVAL;
234 234
235 /* eight is the minimum size for request and response frames */ 235 /* eight is the minimum size for request and response frames */
236 if (blk_rq_bytes(req) < 8 || blk_rq_bytes(rsp) < 8) 236 if (job->request_payload.payload_len < 8 ||
237 job->reply_payload.payload_len < 8)
237 goto out; 238 goto out;
238 239
239 if (bio_offset(req->bio) + blk_rq_bytes(req) > PAGE_SIZE || 240 error = -ENOMEM;
240 bio_offset(rsp->bio) + blk_rq_bytes(rsp) > PAGE_SIZE) { 241 req_data = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
241 shost_printk(KERN_ERR, shost, 242 if (!req_data)
242 "SMP request/response frame crosses page boundary");
243 goto out; 243 goto out;
244 } 244 sg_copy_to_buffer(job->request_payload.sg_list,
245 245 job->request_payload.sg_cnt, req_data,
246 req_data = kzalloc(blk_rq_bytes(req), GFP_KERNEL); 246 job->request_payload.payload_len);
247 247
248 /* make sure frame can always be built ... we copy 248 /* make sure frame can always be built ... we copy
249 * back only the requested length */ 249 * back only the requested length */
250 resp_data = kzalloc(max(blk_rq_bytes(rsp), 128U), GFP_KERNEL); 250 resp_data = kzalloc(max(job->reply_payload.payload_len, 128U),
251 251 GFP_KERNEL);
252 if (!req_data || !resp_data) { 252 if (!resp_data)
253 error = -ENOMEM; 253 goto out_free_req;
254 goto out;
255 }
256
257 local_irq_disable();
258 buf = kmap_atomic(bio_page(req->bio));
259 memcpy(req_data, buf, blk_rq_bytes(req));
260 kunmap_atomic(buf - bio_offset(req->bio));
261 local_irq_enable();
262 254
255 error = -EINVAL;
263 if (req_data[0] != SMP_REQUEST) 256 if (req_data[0] != SMP_REQUEST)
264 goto out; 257 goto out_free_resp;
265
266 /* always succeeds ... even if we can't process the request
267 * the result is in the response frame */
268 error = 0;
269 258
270 /* set up default don't know response */ 259 /* set up default don't know response */
271 resp_data[0] = SMP_RESPONSE; 260 resp_data[0] = SMP_RESPONSE;
@@ -274,20 +263,18 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
274 263
275 switch (req_data[1]) { 264 switch (req_data[1]) {
276 case SMP_REPORT_GENERAL: 265 case SMP_REPORT_GENERAL:
277 scsi_req(req)->resid_len -= 8;
278 scsi_req(rsp)->resid_len -= 32;
279 resp_data[2] = SMP_RESP_FUNC_ACC; 266 resp_data[2] = SMP_RESP_FUNC_ACC;
280 resp_data[9] = sas_ha->num_phys; 267 resp_data[9] = sas_ha->num_phys;
268 reslen = 32;
281 break; 269 break;
282 270
283 case SMP_REPORT_MANUF_INFO: 271 case SMP_REPORT_MANUF_INFO:
284 scsi_req(req)->resid_len -= 8;
285 scsi_req(rsp)->resid_len -= 64;
286 resp_data[2] = SMP_RESP_FUNC_ACC; 272 resp_data[2] = SMP_RESP_FUNC_ACC;
287 memcpy(resp_data + 12, shost->hostt->name, 273 memcpy(resp_data + 12, shost->hostt->name,
288 SAS_EXPANDER_VENDOR_ID_LEN); 274 SAS_EXPANDER_VENDOR_ID_LEN);
289 memcpy(resp_data + 20, "libsas virt phy", 275 memcpy(resp_data + 20, "libsas virt phy",
290 SAS_EXPANDER_PRODUCT_ID_LEN); 276 SAS_EXPANDER_PRODUCT_ID_LEN);
277 reslen = 64;
291 break; 278 break;
292 279
293 case SMP_READ_GPIO_REG: 280 case SMP_READ_GPIO_REG:
@@ -295,14 +282,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
295 break; 282 break;
296 283
297 case SMP_DISCOVER: 284 case SMP_DISCOVER:
298 scsi_req(req)->resid_len -= 16; 285 if (job->request_payload.payload_len < 16)
299 if ((int)scsi_req(req)->resid_len < 0) { 286 goto out_free_resp;
300 scsi_req(req)->resid_len = 0;
301 error = -EINVAL;
302 goto out;
303 }
304 scsi_req(rsp)->resid_len -= 56;
305 sas_host_smp_discover(sas_ha, resp_data, req_data[9]); 287 sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
288 reslen = 56;
306 break; 289 break;
307 290
308 case SMP_REPORT_PHY_ERR_LOG: 291 case SMP_REPORT_PHY_ERR_LOG:
@@ -311,14 +294,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
311 break; 294 break;
312 295
313 case SMP_REPORT_PHY_SATA: 296 case SMP_REPORT_PHY_SATA:
314 scsi_req(req)->resid_len -= 16; 297 if (job->request_payload.payload_len < 16)
315 if ((int)scsi_req(req)->resid_len < 0) { 298 goto out_free_resp;
316 scsi_req(req)->resid_len = 0;
317 error = -EINVAL;
318 goto out;
319 }
320 scsi_req(rsp)->resid_len -= 60;
321 sas_report_phy_sata(sas_ha, resp_data, req_data[9]); 299 sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
300 reslen = 60;
322 break; 301 break;
323 302
324 case SMP_REPORT_ROUTE_INFO: 303 case SMP_REPORT_ROUTE_INFO:
@@ -330,16 +309,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
330 const int base_frame_size = 11; 309 const int base_frame_size = 11;
331 int to_write = req_data[4]; 310 int to_write = req_data[4];
332 311
333 if (blk_rq_bytes(req) < base_frame_size + to_write * 4 || 312 if (job->request_payload.payload_len <
334 scsi_req(req)->resid_len < base_frame_size + to_write * 4) { 313 base_frame_size + to_write * 4) {
335 resp_data[2] = SMP_RESP_INV_FRM_LEN; 314 resp_data[2] = SMP_RESP_INV_FRM_LEN;
336 break; 315 break;
337 } 316 }
338 317
339 to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2], 318 to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
340 req_data[3], to_write, &req_data[8]); 319 req_data[3], to_write, &req_data[8]);
341 scsi_req(req)->resid_len -= base_frame_size + to_write * 4; 320 reslen = 8;
342 scsi_req(rsp)->resid_len -= 8;
343 break; 321 break;
344 } 322 }
345 323
@@ -348,16 +326,12 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
348 break; 326 break;
349 327
350 case SMP_PHY_CONTROL: 328 case SMP_PHY_CONTROL:
351 scsi_req(req)->resid_len -= 44; 329 if (job->request_payload.payload_len < 44)
352 if ((int)scsi_req(req)->resid_len < 0) { 330 goto out_free_resp;
353 scsi_req(req)->resid_len = 0;
354 error = -EINVAL;
355 goto out;
356 }
357 scsi_req(rsp)->resid_len -= 8;
358 sas_phy_control(sas_ha, req_data[9], req_data[10], 331 sas_phy_control(sas_ha, req_data[9], req_data[10],
359 req_data[32] >> 4, req_data[33] >> 4, 332 req_data[32] >> 4, req_data[33] >> 4,
360 resp_data); 333 resp_data);
334 reslen = 8;
361 break; 335 break;
362 336
363 case SMP_PHY_TEST_FUNCTION: 337 case SMP_PHY_TEST_FUNCTION:
@@ -369,15 +343,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
369 break; 343 break;
370 } 344 }
371 345
372 local_irq_disable(); 346 sg_copy_from_buffer(job->reply_payload.sg_list,
373 buf = kmap_atomic(bio_page(rsp->bio)); 347 job->reply_payload.sg_cnt, resp_data,
374 memcpy(buf, resp_data, blk_rq_bytes(rsp)); 348 job->reply_payload.payload_len);
375 flush_kernel_dcache_page(bio_page(rsp->bio));
376 kunmap_atomic(buf - bio_offset(rsp->bio));
377 local_irq_enable();
378 349
379 out: 350 error = 0;
380 kfree(req_data); 351out_free_resp:
381 kfree(resp_data); 352 kfree(resp_data);
382 return error; 353out_free_req:
354 kfree(req_data);
355out:
356 bsg_job_done(job, error, reslen);
383} 357}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index a216c957b639..c07e08136491 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -81,6 +81,8 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw);
81int sas_notify_lldd_dev_found(struct domain_device *); 81int sas_notify_lldd_dev_found(struct domain_device *);
82void sas_notify_lldd_dev_gone(struct domain_device *); 82void sas_notify_lldd_dev_gone(struct domain_device *);
83 83
84void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
85 struct sas_rphy *rphy);
84int sas_smp_phy_control(struct domain_device *dev, int phy_id, 86int sas_smp_phy_control(struct domain_device *dev, int phy_id,
85 enum phy_func phy_func, struct sas_phy_linkrates *); 87 enum phy_func phy_func, struct sas_phy_linkrates *);
86int sas_smp_get_phy_events(struct sas_phy *phy); 88int sas_smp_get_phy_events(struct sas_phy *phy);
@@ -98,16 +100,14 @@ void sas_hae_reset(struct work_struct *work);
98void sas_free_device(struct kref *kref); 100void sas_free_device(struct kref *kref);
99 101
100#ifdef CONFIG_SCSI_SAS_HOST_SMP 102#ifdef CONFIG_SCSI_SAS_HOST_SMP
101extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, 103extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost);
102 struct request *rsp);
103#else 104#else
104static inline int sas_smp_host_handler(struct Scsi_Host *shost, 105static inline void sas_smp_host_handler(struct bsg_job *job,
105 struct request *req, 106 struct Scsi_Host *shost)
106 struct request *rsp)
107{ 107{
108 shost_printk(KERN_ERR, shost, 108 shost_printk(KERN_ERR, shost,
109 "Cannot send SMP to a sas host (not enabled in CONFIG)\n"); 109 "Cannot send SMP to a sas host (not enabled in CONFIG)\n");
110 return -EINVAL; 110 bsg_job_done(job, -EINVAL, 0);
111} 111}
112#endif 112#endif
113 113
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index e7a7a704a315..d3940c5d079d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -1870,6 +1870,38 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1870 return rc; 1870 return rc;
1871} 1871}
1872 1872
1873static int
1874_transport_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1875 dma_addr_t *dma_addr, size_t *dma_len, void **p)
1876{
1877 /* Check if the request is split across multiple segments */
1878 if (buf->sg_cnt > 1) {
1879 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
1880 GFP_KERNEL);
1881 if (!*p)
1882 return -ENOMEM;
1883 *dma_len = buf->payload_len;
1884 } else {
1885 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
1886 return -ENOMEM;
1887 *dma_addr = sg_dma_address(buf->sg_list);
1888 *dma_len = sg_dma_len(buf->sg_list);
1889 *p = NULL;
1890 }
1891
1892 return 0;
1893}
1894
1895static void
1896_transport_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1897 dma_addr_t dma_addr, void *p)
1898{
1899 if (p)
1900 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
1901 else
1902 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
1903}
1904
1873/** 1905/**
1874 * _transport_smp_handler - transport portal for smp passthru 1906 * _transport_smp_handler - transport portal for smp passthru
1875 * @shost: shost object 1907 * @shost: shost object
@@ -1880,9 +1912,9 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1880 * Example: 1912 * Example:
1881 * smp_rep_general /sys/class/bsg/expander-5:0 1913 * smp_rep_general /sys/class/bsg/expander-5:0
1882 */ 1914 */
1883static int 1915static void
1884_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, 1916_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
1885 struct request *req) 1917 struct sas_rphy *rphy)
1886{ 1918{
1887 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); 1919 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1888 Mpi2SmpPassthroughRequest_t *mpi_request; 1920 Mpi2SmpPassthroughRequest_t *mpi_request;
@@ -1891,33 +1923,25 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1891 u16 smid; 1923 u16 smid;
1892 u32 ioc_state; 1924 u32 ioc_state;
1893 void *psge; 1925 void *psge;
1894 u8 issue_reset = 0; 1926 dma_addr_t dma_addr_in;
1895 dma_addr_t dma_addr_in = 0; 1927 dma_addr_t dma_addr_out;
1896 dma_addr_t dma_addr_out = 0; 1928 void *addr_in = NULL;
1897 dma_addr_t pci_dma_in = 0; 1929 void *addr_out = NULL;
1898 dma_addr_t pci_dma_out = 0; 1930 size_t dma_len_in;
1899 void *pci_addr_in = NULL; 1931 size_t dma_len_out;
1900 void *pci_addr_out = NULL;
1901 u16 wait_state_count; 1932 u16 wait_state_count;
1902 struct request *rsp = req->next_rq; 1933 unsigned int reslen = 0;
1903 struct bio_vec bvec;
1904 struct bvec_iter iter;
1905
1906 if (!rsp) {
1907 pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n",
1908 ioc->name, __func__);
1909 return -EINVAL;
1910 }
1911 1934
1912 if (ioc->shost_recovery || ioc->pci_error_recovery) { 1935 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1913 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", 1936 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1914 __func__, ioc->name); 1937 __func__, ioc->name);
1915 return -EFAULT; 1938 rc = -EFAULT;
1939 goto out;
1916 } 1940 }
1917 1941
1918 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); 1942 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1919 if (rc) 1943 if (rc)
1920 return rc; 1944 goto out;
1921 1945
1922 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { 1946 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1923 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name, 1947 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name,
@@ -1927,58 +1951,20 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1927 } 1951 }
1928 ioc->transport_cmds.status = MPT3_CMD_PENDING; 1952 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1929 1953
1930 /* Check if the request is split across multiple segments */ 1954 rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->request_payload,
1931 if (bio_multiple_segments(req->bio)) { 1955 &dma_addr_out, &dma_len_out, &addr_out);
1932 u32 offset = 0; 1956 if (rc)
1933 1957 goto out;
1934 /* Allocate memory and copy the request */ 1958 if (addr_out) {
1935 pci_addr_out = pci_alloc_consistent(ioc->pdev, 1959 sg_copy_to_buffer(job->request_payload.sg_list,
1936 blk_rq_bytes(req), &pci_dma_out); 1960 job->request_payload.sg_cnt, addr_out,
1937 if (!pci_addr_out) { 1961 job->request_payload.payload_len);
1938 pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n",
1939 ioc->name, __func__);
1940 rc = -ENOMEM;
1941 goto out;
1942 }
1943
1944 bio_for_each_segment(bvec, req->bio, iter) {
1945 memcpy(pci_addr_out + offset,
1946 page_address(bvec.bv_page) + bvec.bv_offset,
1947 bvec.bv_len);
1948 offset += bvec.bv_len;
1949 }
1950 } else {
1951 dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1952 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1953 if (pci_dma_mapping_error(ioc->pdev, dma_addr_out)) {
1954 pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n",
1955 ioc->name, __func__);
1956 rc = -ENOMEM;
1957 goto free_pci;
1958 }
1959 } 1962 }
1960 1963
1961 /* Check if the response needs to be populated across 1964 rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
1962 * multiple segments */ 1965 &dma_addr_in, &dma_len_in, &addr_in);
1963 if (bio_multiple_segments(rsp->bio)) { 1966 if (rc)
1964 pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), 1967 goto unmap_out;
1965 &pci_dma_in);
1966 if (!pci_addr_in) {
1967 pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n",
1968 ioc->name, __func__);
1969 rc = -ENOMEM;
1970 goto unmap;
1971 }
1972 } else {
1973 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1974 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1975 if (pci_dma_mapping_error(ioc->pdev, dma_addr_in)) {
1976 pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n",
1977 ioc->name, __func__);
1978 rc = -ENOMEM;
1979 goto unmap;
1980 }
1981 }
1982 1968
1983 wait_state_count = 0; 1969 wait_state_count = 0;
1984 ioc_state = mpt3sas_base_get_iocstate(ioc, 1); 1970 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
@@ -1988,7 +1974,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1988 "%s: failed due to ioc not operational\n", 1974 "%s: failed due to ioc not operational\n",
1989 ioc->name, __func__); 1975 ioc->name, __func__);
1990 rc = -EFAULT; 1976 rc = -EFAULT;
1991 goto unmap; 1977 goto unmap_in;
1992 } 1978 }
1993 ssleep(1); 1979 ssleep(1);
1994 ioc_state = mpt3sas_base_get_iocstate(ioc, 1); 1980 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
@@ -2005,7 +1991,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2005 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", 1991 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2006 ioc->name, __func__); 1992 ioc->name, __func__);
2007 rc = -EAGAIN; 1993 rc = -EAGAIN;
2008 goto unmap; 1994 goto unmap_in;
2009 } 1995 }
2010 1996
2011 rc = 0; 1997 rc = 0;
@@ -2018,15 +2004,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2018 mpi_request->SASAddress = (rphy) ? 2004 mpi_request->SASAddress = (rphy) ?
2019 cpu_to_le64(rphy->identify.sas_address) : 2005 cpu_to_le64(rphy->identify.sas_address) :
2020 cpu_to_le64(ioc->sas_hba.sas_address); 2006 cpu_to_le64(ioc->sas_hba.sas_address);
2021 mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); 2007 mpi_request->RequestDataLength = cpu_to_le16(dma_len_out - 4);
2022 psge = &mpi_request->SGL; 2008 psge = &mpi_request->SGL;
2023 2009
2024 if (bio_multiple_segments(req->bio)) 2010 ioc->build_sg(ioc, psge, dma_addr_out, dma_len_out - 4, dma_addr_in,
2025 ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4), 2011 dma_len_in - 4);
2026 pci_dma_in, (blk_rq_bytes(rsp) + 4));
2027 else
2028 ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4),
2029 dma_addr_in, (blk_rq_bytes(rsp) + 4));
2030 2012
2031 dtransportprintk(ioc, pr_info(MPT3SAS_FMT 2013 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2032 "%s - sending smp request\n", ioc->name, __func__)); 2014 "%s - sending smp request\n", ioc->name, __func__));
@@ -2040,83 +2022,51 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2040 __func__, ioc->name); 2022 __func__, ioc->name);
2041 _debug_dump_mf(mpi_request, 2023 _debug_dump_mf(mpi_request,
2042 sizeof(Mpi2SmpPassthroughRequest_t)/4); 2024 sizeof(Mpi2SmpPassthroughRequest_t)/4);
2043 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) 2025 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) {
2044 issue_reset = 1; 2026 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
2045 goto issue_host_reset; 2027 rc = -ETIMEDOUT;
2028 goto unmap_in;
2029 }
2046 } 2030 }
2047 2031
2048 dtransportprintk(ioc, pr_info(MPT3SAS_FMT 2032 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2049 "%s - complete\n", ioc->name, __func__)); 2033 "%s - complete\n", ioc->name, __func__));
2050 2034
2051 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { 2035 if (!(ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID)) {
2052
2053 mpi_reply = ioc->transport_cmds.reply;
2054
2055 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2056 "%s - reply data transfer size(%d)\n",
2057 ioc->name, __func__,
2058 le16_to_cpu(mpi_reply->ResponseDataLength)));
2059
2060 memcpy(scsi_req(req)->sense, mpi_reply, sizeof(*mpi_reply));
2061 scsi_req(req)->sense_len = sizeof(*mpi_reply);
2062 scsi_req(req)->resid_len = 0;
2063 scsi_req(rsp)->resid_len -=
2064 le16_to_cpu(mpi_reply->ResponseDataLength);
2065
2066 /* check if the resp needs to be copied from the allocated
2067 * pci mem */
2068 if (bio_multiple_segments(rsp->bio)) {
2069 u32 offset = 0;
2070 u32 bytes_to_copy =
2071 le16_to_cpu(mpi_reply->ResponseDataLength);
2072 bio_for_each_segment(bvec, rsp->bio, iter) {
2073 if (bytes_to_copy <= bvec.bv_len) {
2074 memcpy(page_address(bvec.bv_page) +
2075 bvec.bv_offset, pci_addr_in +
2076 offset, bytes_to_copy);
2077 break;
2078 } else {
2079 memcpy(page_address(bvec.bv_page) +
2080 bvec.bv_offset, pci_addr_in +
2081 offset, bvec.bv_len);
2082 bytes_to_copy -= bvec.bv_len;
2083 }
2084 offset += bvec.bv_len;
2085 }
2086 }
2087 } else {
2088 dtransportprintk(ioc, pr_info(MPT3SAS_FMT 2036 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2089 "%s - no reply\n", ioc->name, __func__)); 2037 "%s - no reply\n", ioc->name, __func__));
2090 rc = -ENXIO; 2038 rc = -ENXIO;
2039 goto unmap_in;
2091 } 2040 }
2092 2041
2093 issue_host_reset: 2042 mpi_reply = ioc->transport_cmds.reply;
2094 if (issue_reset) {
2095 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
2096 rc = -ETIMEDOUT;
2097 }
2098 2043
2099 unmap: 2044 dtransportprintk(ioc,
2100 if (dma_addr_out) 2045 pr_info(MPT3SAS_FMT "%s - reply data transfer size(%d)\n",
2101 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req), 2046 ioc->name, __func__,
2102 PCI_DMA_BIDIRECTIONAL); 2047 le16_to_cpu(mpi_reply->ResponseDataLength)));
2103 if (dma_addr_in)
2104 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2105 PCI_DMA_BIDIRECTIONAL);
2106 2048
2107 free_pci: 2049 memcpy(job->reply, mpi_reply, sizeof(*mpi_reply));
2108 if (pci_addr_out) 2050 job->reply_len = sizeof(*mpi_reply);
2109 pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out, 2051 reslen = le16_to_cpu(mpi_reply->ResponseDataLength);
2110 pci_dma_out);
2111 2052
2112 if (pci_addr_in) 2053 if (addr_in) {
2113 pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in, 2054 sg_copy_to_buffer(job->reply_payload.sg_list,
2114 pci_dma_in); 2055 job->reply_payload.sg_cnt, addr_in,
2056 job->reply_payload.payload_len);
2057 }
2115 2058
2059 rc = 0;
2060 unmap_in:
2061 _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
2062 dma_addr_in, addr_in);
2063 unmap_out:
2064 _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->request_payload,
2065 dma_addr_out, addr_out);
2116 out: 2066 out:
2117 ioc->transport_cmds.status = MPT3_CMD_NOT_USED; 2067 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
2118 mutex_unlock(&ioc->transport_cmds.mutex); 2068 mutex_unlock(&ioc->transport_cmds.mutex);
2119 return rc; 2069 bsg_job_done(job, rc, reslen);
2120} 2070}
2121 2071
2122struct sas_function_template mpt3sas_transport_functions = { 2072struct sas_function_template mpt3sas_transport_functions = {
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index e2e948f1ce28..319dff970237 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -169,39 +169,22 @@ static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
169 return rdev; 169 return rdev;
170} 170}
171 171
172static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, 172static int sas_smp_dispatch(struct bsg_job *job)
173 struct sas_rphy *rphy)
174{ 173{
175 struct request *req; 174 struct Scsi_Host *shost = dev_to_shost(job->dev);
176 blk_status_t ret; 175 struct sas_rphy *rphy = NULL;
177 int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
178 176
179 while ((req = blk_fetch_request(q)) != NULL) { 177 if (!scsi_is_host_device(job->dev))
180 spin_unlock_irq(q->queue_lock); 178 rphy = dev_to_rphy(job->dev);
181 179
182 scsi_req(req)->resid_len = blk_rq_bytes(req); 180 if (!job->req->next_rq) {
183 if (req->next_rq) 181 dev_warn(job->dev, "space for a smp response is missing\n");
184 scsi_req(req->next_rq)->resid_len = 182 bsg_job_done(job, -EINVAL, 0);
185 blk_rq_bytes(req->next_rq); 183 return 0;
186 handler = to_sas_internal(shost->transportt)->f->smp_handler;
187 ret = handler(shost, rphy, req);
188 scsi_req(req)->result = ret;
189
190 blk_end_request_all(req, 0);
191
192 spin_lock_irq(q->queue_lock);
193 } 184 }
194}
195 185
196static void sas_host_smp_request(struct request_queue *q) 186 to_sas_internal(shost->transportt)->f->smp_handler(job, shost, rphy);
197{ 187 return 0;
198 sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
199}
200
201static void sas_non_host_smp_request(struct request_queue *q)
202{
203 struct sas_rphy *rphy = q->queuedata;
204 sas_smp_request(q, rphy_to_shost(rphy), rphy);
205} 188}
206 189
207static void sas_host_release(struct device *dev) 190static void sas_host_release(struct device *dev)
@@ -217,81 +200,36 @@ static void sas_host_release(struct device *dev)
217static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) 200static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
218{ 201{
219 struct request_queue *q; 202 struct request_queue *q;
220 int error;
221 struct device *dev;
222 char namebuf[20];
223 const char *name;
224 void (*release)(struct device *);
225 203
226 if (!to_sas_internal(shost->transportt)->f->smp_handler) { 204 if (!to_sas_internal(shost->transportt)->f->smp_handler) {
227 printk("%s can't handle SMP requests\n", shost->hostt->name); 205 printk("%s can't handle SMP requests\n", shost->hostt->name);
228 return 0; 206 return 0;
229 } 207 }
230 208
231 q = blk_alloc_queue(GFP_KERNEL);
232 if (!q)
233 return -ENOMEM;
234 q->initialize_rq_fn = scsi_initialize_rq;
235 q->cmd_size = sizeof(struct scsi_request);
236
237 if (rphy) { 209 if (rphy) {
238 q->request_fn = sas_non_host_smp_request; 210 q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev),
239 dev = &rphy->dev; 211 sas_smp_dispatch, 0, NULL);
240 name = dev_name(dev); 212 if (IS_ERR(q))
241 release = NULL; 213 return PTR_ERR(q);
214 rphy->q = q;
242 } else { 215 } else {
243 q->request_fn = sas_host_smp_request; 216 char name[20];
244 dev = &shost->shost_gendev; 217
245 snprintf(namebuf, sizeof(namebuf), 218 snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
246 "sas_host%d", shost->host_no); 219 q = bsg_setup_queue(&shost->shost_gendev, name,
247 name = namebuf; 220 sas_smp_dispatch, 0, sas_host_release);
248 release = sas_host_release; 221 if (IS_ERR(q))
222 return PTR_ERR(q);
223 to_sas_host_attrs(shost)->q = q;
249 } 224 }
250 error = blk_init_allocated_queue(q);
251 if (error)
252 goto out_cleanup_queue;
253 225
254 /* 226 /*
255 * by default assume old behaviour and bounce for any highmem page 227 * by default assume old behaviour and bounce for any highmem page
256 */ 228 */
257 blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); 229 blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
258
259 error = bsg_register_queue(q, dev, name, release);
260 if (error)
261 goto out_cleanup_queue;
262
263 if (rphy)
264 rphy->q = q;
265 else
266 to_sas_host_attrs(shost)->q = q;
267
268 if (rphy)
269 q->queuedata = rphy;
270 else
271 q->queuedata = shost;
272
273 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); 230 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
274 queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q); 231 queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
275 return 0; 232 return 0;
276
277out_cleanup_queue:
278 blk_cleanup_queue(q);
279 return error;
280}
281
282static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
283{
284 struct request_queue *q;
285
286 if (rphy)
287 q = rphy->q;
288 else
289 q = to_sas_host_attrs(shost)->q;
290
291 if (!q)
292 return;
293
294 bsg_unregister_queue(q);
295} 233}
296 234
297/* 235/*
@@ -321,9 +259,10 @@ static int sas_host_remove(struct transport_container *tc, struct device *dev,
321 struct device *cdev) 259 struct device *cdev)
322{ 260{
323 struct Scsi_Host *shost = dev_to_shost(dev); 261 struct Scsi_Host *shost = dev_to_shost(dev);
262 struct request_queue *q = to_sas_host_attrs(shost)->q;
324 263
325 sas_bsg_remove(shost, NULL); 264 if (q)
326 265 bsg_unregister_queue(q);
327 return 0; 266 return 0;
328} 267}
329 268
@@ -1713,7 +1652,8 @@ sas_rphy_remove(struct sas_rphy *rphy)
1713 } 1652 }
1714 1653
1715 sas_rphy_unlink(rphy); 1654 sas_rphy_unlink(rphy);
1716 sas_bsg_remove(NULL, rphy); 1655 if (rphy->q)
1656 bsg_unregister_queue(rphy->q);
1717 transport_remove_device(dev); 1657 transport_remove_device(dev);
1718 device_del(dev); 1658 device_del(dev);
1719} 1659}