Commit | Line | Data |
---|---|---|
115bb1ff MW |
1 | /* |
2 | * USB Attached SCSI | |
3 | * Note that this is not the same as the USB Mass Storage driver | |
4 | * | |
5df2be63 | 5 | * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013 - 2014 |
115bb1ff MW |
6 | * Copyright Matthew Wilcox for Intel Corp, 2010 |
7 | * Copyright Sarah Sharp for Intel Corp, 2010 | |
8 | * | |
9 | * Distributed under the terms of the GNU GPL, version two. | |
10 | */ | |
11 | ||
12 | #include <linux/blkdev.h> | |
13 | #include <linux/slab.h> | |
14 | #include <linux/types.h> | |
6eb0de82 | 15 | #include <linux/module.h> |
115bb1ff | 16 | #include <linux/usb.h> |
79b4c061 | 17 | #include <linux/usb_usual.h> |
c898add5 | 18 | #include <linux/usb/hcd.h> |
115bb1ff | 19 | #include <linux/usb/storage.h> |
348748b0 | 20 | #include <linux/usb/uas.h> |
115bb1ff MW |
21 | |
22 | #include <scsi/scsi.h> | |
4de7a373 | 23 | #include <scsi/scsi_eh.h> |
115bb1ff MW |
24 | #include <scsi/scsi_dbg.h> |
25 | #include <scsi/scsi_cmnd.h> | |
26 | #include <scsi/scsi_device.h> | |
27 | #include <scsi/scsi_host.h> | |
28 | #include <scsi/scsi_tcq.h> | |
29 | ||
82aa0387 | 30 | #include "uas-detect.h" |
59307852 | 31 | #include "scsiglue.h" |
82aa0387 | 32 | |
5e61aede | 33 | #define MAX_CMNDS 256 |
115bb1ff | 34 | |
115bb1ff MW |
35 | struct uas_dev_info { |
36 | struct usb_interface *intf; | |
37 | struct usb_device *udev; | |
a0e39e34 | 38 | struct usb_anchor cmd_urbs; |
bdd000fb GH |
39 | struct usb_anchor sense_urbs; |
40 | struct usb_anchor data_urbs; | |
59307852 | 41 | unsigned long flags; |
023b515e | 42 | int qdepth, resetting; |
115bb1ff MW |
43 | unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; |
44 | unsigned use_streams:1; | |
da65c2bb | 45 | unsigned shutdown:1; |
5e61aede | 46 | struct scsi_cmnd *cmnd[MAX_CMNDS]; |
e0648520 | 47 | spinlock_t lock; |
1bf8198e | 48 | struct work_struct work; |
115bb1ff MW |
49 | }; |
50 | ||
51 | enum { | |
92a3f767 | 52 | SUBMIT_STATUS_URB = (1 << 1), |
115bb1ff MW |
53 | ALLOC_DATA_IN_URB = (1 << 2), |
54 | SUBMIT_DATA_IN_URB = (1 << 3), | |
55 | ALLOC_DATA_OUT_URB = (1 << 4), | |
56 | SUBMIT_DATA_OUT_URB = (1 << 5), | |
57 | ALLOC_CMD_URB = (1 << 6), | |
58 | SUBMIT_CMD_URB = (1 << 7), | |
b1d67693 GH |
59 | COMMAND_INFLIGHT = (1 << 8), |
60 | DATA_IN_URB_INFLIGHT = (1 << 9), | |
61 | DATA_OUT_URB_INFLIGHT = (1 << 10), | |
eb7d664a HG |
62 | COMMAND_ABORTED = (1 << 11), |
63 | IS_IN_WORK_LIST = (1 << 12), | |
115bb1ff MW |
64 | }; |
65 | ||
66 | /* Overrides scsi_pointer */ | |
67 | struct uas_cmd_info { | |
68 | unsigned int state; | |
69 | unsigned int stream; | |
70 | struct urb *cmd_urb; | |
115bb1ff MW |
71 | struct urb *data_in_urb; |
72 | struct urb *data_out_urb; | |
115bb1ff MW |
73 | }; |
74 | ||
75 | /* I hate forward declarations, but I actually have a loop */ | |
76 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, | |
77 | struct uas_dev_info *devinfo, gfp_t gfp); | |
ea9da1c7 | 78 | static void uas_do_work(struct work_struct *work); |
4c456971 | 79 | static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller); |
d89bd835 | 80 | static void uas_free_streams(struct uas_dev_info *devinfo); |
1ad7ed5a HG |
81 | static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix, |
82 | int status); | |
aa8f6123 | 83 | |
115bb1ff MW |
84 | static void uas_do_work(struct work_struct *work) |
85 | { | |
1bf8198e GH |
86 | struct uas_dev_info *devinfo = |
87 | container_of(work, struct uas_dev_info, work); | |
115bb1ff | 88 | struct uas_cmd_info *cmdinfo; |
43cd99cb | 89 | struct scsi_cmnd *cmnd; |
e0648520 | 90 | unsigned long flags; |
43cd99cb | 91 | int i, err; |
115bb1ff | 92 | |
1bf8198e | 93 | spin_lock_irqsave(&devinfo->lock, flags); |
b7b5d11f HG |
94 | |
95 | if (devinfo->resetting) | |
96 | goto out; | |
97 | ||
43cd99cb HG |
98 | for (i = 0; i < devinfo->qdepth; i++) { |
99 | if (!devinfo->cmnd[i]) | |
100 | continue; | |
101 | ||
102 | cmnd = devinfo->cmnd[i]; | |
103 | cmdinfo = (void *)&cmnd->SCp; | |
61c09ce5 HG |
104 | |
105 | if (!(cmdinfo->state & IS_IN_WORK_LIST)) | |
106 | continue; | |
107 | ||
e7eda932 | 108 | err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); |
61c09ce5 | 109 | if (!err) |
efefecf3 | 110 | cmdinfo->state &= ~IS_IN_WORK_LIST; |
61c09ce5 | 111 | else |
1bf8198e | 112 | schedule_work(&devinfo->work); |
115bb1ff | 113 | } |
b7b5d11f | 114 | out: |
4c456971 GH |
115 | spin_unlock_irqrestore(&devinfo->lock, flags); |
116 | } | |
117 | ||
1bf8198e GH |
118 | static void uas_add_work(struct uas_cmd_info *cmdinfo) |
119 | { | |
120 | struct scsi_pointer *scp = (void *)cmdinfo; | |
121 | struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); | |
122 | struct uas_dev_info *devinfo = cmnd->device->hostdata; | |
123 | ||
ab945eff | 124 | lockdep_assert_held(&devinfo->lock); |
1bf8198e GH |
125 | cmdinfo->state |= IS_IN_WORK_LIST; |
126 | schedule_work(&devinfo->work); | |
127 | } | |
128 | ||
1589349f | 129 | static void uas_zap_pending(struct uas_dev_info *devinfo, int result) |
326349f8 GH |
130 | { |
131 | struct uas_cmd_info *cmdinfo; | |
43cd99cb | 132 | struct scsi_cmnd *cmnd; |
326349f8 | 133 | unsigned long flags; |
43cd99cb | 134 | int i, err; |
326349f8 GH |
135 | |
136 | spin_lock_irqsave(&devinfo->lock, flags); | |
43cd99cb HG |
137 | for (i = 0; i < devinfo->qdepth; i++) { |
138 | if (!devinfo->cmnd[i]) | |
139 | continue; | |
140 | ||
141 | cmnd = devinfo->cmnd[i]; | |
142 | cmdinfo = (void *)&cmnd->SCp; | |
1ad7ed5a | 143 | uas_log_cmd_state(cmnd, __func__, 0); |
9c15c573 HG |
144 | /* Sense urbs were killed, clear COMMAND_INFLIGHT manually */ |
145 | cmdinfo->state &= ~COMMAND_INFLIGHT; | |
1589349f | 146 | cmnd->result = result << 16; |
9c15c573 HG |
147 | err = uas_try_complete(cmnd, __func__); |
148 | WARN_ON(err != 0); | |
326349f8 GH |
149 | } |
150 | spin_unlock_irqrestore(&devinfo->lock, flags); | |
151 | } | |
152 | ||
115bb1ff MW |
153 | static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) |
154 | { | |
155 | struct sense_iu *sense_iu = urb->transfer_buffer; | |
156 | struct scsi_device *sdev = cmnd->device; | |
157 | ||
158 | if (urb->actual_length > 16) { | |
159 | unsigned len = be16_to_cpup(&sense_iu->len); | |
160 | if (len + 16 != urb->actual_length) { | |
161 | int newlen = min(len + 16, urb->actual_length) - 16; | |
162 | if (newlen < 0) | |
163 | newlen = 0; | |
164 | sdev_printk(KERN_INFO, sdev, "%s: urb length %d " | |
165 | "disagrees with IU sense data length %d, " | |
166 | "using %d bytes of sense data\n", __func__, | |
167 | urb->actual_length, len, newlen); | |
168 | len = newlen; | |
169 | } | |
170 | memcpy(cmnd->sense_buffer, sense_iu->sense, len); | |
171 | } | |
172 | ||
173 | cmnd->result = sense_iu->status; | |
115bb1ff MW |
174 | } |
175 | ||
e0620001 HG |
176 | /* |
177 | * scsi-tags go from 0 - (nr_tags - 1), uas tags need to match stream-ids, | |
178 | * which go from 1 - nr_streams. And we use 1 for untagged commands. | |
179 | */ | |
180 | static int uas_get_tag(struct scsi_cmnd *cmnd) | |
115bb1ff | 181 | { |
e0620001 | 182 | int tag; |
115bb1ff | 183 | |
e0620001 HG |
184 | if (blk_rq_tagged(cmnd->request)) |
185 | tag = cmnd->request->tag + 2; | |
186 | else | |
187 | tag = 1; | |
115bb1ff | 188 | |
e0620001 | 189 | return tag; |
b1d67693 GH |
190 | } |
191 | ||
1ad7ed5a HG |
192 | static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix, |
193 | int status) | |
b1d67693 GH |
194 | { |
195 | struct uas_cmd_info *ci = (void *)&cmnd->SCp; | |
196 | ||
60d9f67d | 197 | scmd_printk(KERN_INFO, cmnd, |
1ad7ed5a HG |
198 | "%s %d tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ", |
199 | prefix, status, uas_get_tag(cmnd), | |
b1d67693 GH |
200 | (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", |
201 | (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", | |
202 | (ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "", | |
203 | (ci->state & ALLOC_DATA_OUT_URB) ? " a-out" : "", | |
204 | (ci->state & SUBMIT_DATA_OUT_URB) ? " s-out" : "", | |
205 | (ci->state & ALLOC_CMD_URB) ? " a-cmd" : "", | |
206 | (ci->state & SUBMIT_CMD_URB) ? " s-cmd" : "", | |
207 | (ci->state & COMMAND_INFLIGHT) ? " CMD" : "", | |
208 | (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "", | |
209 | (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "", | |
b06e48af | 210 | (ci->state & COMMAND_ABORTED) ? " abort" : "", |
efefecf3 | 211 | (ci->state & IS_IN_WORK_LIST) ? " work" : ""); |
6dcd8ec2 | 212 | scsi_print_command(cmnd); |
b1d67693 GH |
213 | } |
214 | ||
4c5481ef HG |
215 | static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd) |
216 | { | |
217 | struct uas_cmd_info *cmdinfo; | |
218 | ||
219 | if (!cmnd) | |
220 | return; | |
221 | ||
222 | cmdinfo = (void *)&cmnd->SCp; | |
223 | ||
224 | if (cmdinfo->state & SUBMIT_CMD_URB) | |
225 | usb_free_urb(cmdinfo->cmd_urb); | |
226 | ||
227 | /* data urbs may have never gotten their submit flag set */ | |
228 | if (!(cmdinfo->state & DATA_IN_URB_INFLIGHT)) | |
229 | usb_free_urb(cmdinfo->data_in_urb); | |
230 | if (!(cmdinfo->state & DATA_OUT_URB_INFLIGHT)) | |
231 | usb_free_urb(cmdinfo->data_out_urb); | |
b1d67693 GH |
232 | } |
233 | ||
234 | static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) | |
235 | { | |
236 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
e0648520 | 237 | struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; |
b1d67693 | 238 | |
ab945eff | 239 | lockdep_assert_held(&devinfo->lock); |
b1d67693 GH |
240 | if (cmdinfo->state & (COMMAND_INFLIGHT | |
241 | DATA_IN_URB_INFLIGHT | | |
b06e48af | 242 | DATA_OUT_URB_INFLIGHT | |
616f0e6c | 243 | COMMAND_ABORTED)) |
b1d67693 | 244 | return -EBUSY; |
5e61aede | 245 | devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL; |
4c5481ef | 246 | uas_free_unsubmitted_urbs(cmnd); |
c621a81e | 247 | cmnd->scsi_done(cmnd); |
b1d67693 | 248 | return 0; |
115bb1ff MW |
249 | } |
250 | ||
251 | static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, | |
b1d67693 | 252 | unsigned direction) |
115bb1ff MW |
253 | { |
254 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
255 | int err; | |
256 | ||
b1d67693 | 257 | cmdinfo->state |= direction | SUBMIT_STATUS_URB; |
115bb1ff MW |
258 | err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); |
259 | if (err) { | |
1bf8198e | 260 | uas_add_work(cmdinfo); |
115bb1ff MW |
261 | } |
262 | } | |
263 | ||
264 | static void uas_stat_cmplt(struct urb *urb) | |
265 | { | |
266 | struct iu *iu = urb->transfer_buffer; | |
22188f4a | 267 | struct Scsi_Host *shost = urb->context; |
21fc05b6 | 268 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
60d9f67d HG |
269 | struct urb *data_in_urb = NULL; |
270 | struct urb *data_out_urb = NULL; | |
115bb1ff | 271 | struct scsi_cmnd *cmnd; |
b1d67693 | 272 | struct uas_cmd_info *cmdinfo; |
e0648520 | 273 | unsigned long flags; |
5e61aede | 274 | unsigned int idx; |
115bb1ff | 275 | |
b7b5d11f HG |
276 | spin_lock_irqsave(&devinfo->lock, flags); |
277 | ||
278 | if (devinfo->resetting) | |
279 | goto out; | |
115bb1ff MW |
280 | |
281 | if (urb->status) { | |
51b36173 | 282 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { |
326349f8 GH |
283 | dev_err(&urb->dev->dev, "stat urb: status %d\n", |
284 | urb->status); | |
285 | } | |
b7b5d11f | 286 | goto out; |
115bb1ff MW |
287 | } |
288 | ||
5e61aede HG |
289 | idx = be16_to_cpup(&iu->tag) - 1; |
290 | if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) { | |
291 | dev_err(&urb->dev->dev, | |
292 | "stat urb: no pending cmd for tag %d\n", idx + 1); | |
b7b5d11f | 293 | goto out; |
023b515e GH |
294 | } |
295 | ||
5e61aede | 296 | cmnd = devinfo->cmnd[idx]; |
e0423dee | 297 | cmdinfo = (void *)&cmnd->SCp; |
d89da03a HG |
298 | |
299 | if (!(cmdinfo->state & COMMAND_INFLIGHT)) { | |
1ad7ed5a | 300 | uas_log_cmd_state(cmnd, "unexpected status cmplt", 0); |
d89da03a | 301 | goto out; |
96c1eb98 | 302 | } |
115bb1ff MW |
303 | |
304 | switch (iu->iu_id) { | |
305 | case IU_ID_STATUS: | |
5ad22cfc | 306 | uas_sense(urb, cmnd); |
8aac863e GH |
307 | if (cmnd->result != 0) { |
308 | /* cancel data transfers on error */ | |
60d9f67d HG |
309 | data_in_urb = usb_get_urb(cmdinfo->data_in_urb); |
310 | data_out_urb = usb_get_urb(cmdinfo->data_out_urb); | |
8aac863e | 311 | } |
b1d67693 GH |
312 | cmdinfo->state &= ~COMMAND_INFLIGHT; |
313 | uas_try_complete(cmnd, __func__); | |
115bb1ff MW |
314 | break; |
315 | case IU_ID_READ_READY: | |
8e453155 HG |
316 | if (!cmdinfo->data_in_urb || |
317 | (cmdinfo->state & DATA_IN_URB_INFLIGHT)) { | |
1ad7ed5a | 318 | uas_log_cmd_state(cmnd, "unexpected read rdy", 0); |
8e453155 HG |
319 | break; |
320 | } | |
115bb1ff MW |
321 | uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB); |
322 | break; | |
323 | case IU_ID_WRITE_READY: | |
8e453155 HG |
324 | if (!cmdinfo->data_out_urb || |
325 | (cmdinfo->state & DATA_OUT_URB_INFLIGHT)) { | |
1ad7ed5a | 326 | uas_log_cmd_state(cmnd, "unexpected write rdy", 0); |
8e453155 HG |
327 | break; |
328 | } | |
115bb1ff MW |
329 | uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); |
330 | break; | |
fac1f485 HG |
331 | case IU_ID_RESPONSE: |
332 | uas_log_cmd_state(cmnd, "unexpected response iu", | |
333 | ((struct response_iu *)iu)->response_code); | |
334 | /* Error, cancel data transfers */ | |
335 | data_in_urb = usb_get_urb(cmdinfo->data_in_urb); | |
336 | data_out_urb = usb_get_urb(cmdinfo->data_out_urb); | |
337 | cmdinfo->state &= ~COMMAND_INFLIGHT; | |
338 | cmnd->result = DID_ERROR << 16; | |
339 | uas_try_complete(cmnd, __func__); | |
340 | break; | |
115bb1ff | 341 | default: |
1ad7ed5a | 342 | uas_log_cmd_state(cmnd, "bogus IU", iu->iu_id); |
115bb1ff | 343 | } |
b7b5d11f | 344 | out: |
e9bd7e1a | 345 | usb_free_urb(urb); |
e0648520 | 346 | spin_unlock_irqrestore(&devinfo->lock, flags); |
60d9f67d HG |
347 | |
348 | /* Unlinking of data urbs must be done without holding the lock */ | |
349 | if (data_in_urb) { | |
350 | usb_unlink_urb(data_in_urb); | |
351 | usb_put_urb(data_in_urb); | |
352 | } | |
353 | if (data_out_urb) { | |
354 | usb_unlink_urb(data_out_urb); | |
355 | usb_put_urb(data_out_urb); | |
356 | } | |
115bb1ff MW |
357 | } |
358 | ||
c621a81e | 359 | static void uas_data_cmplt(struct urb *urb) |
115bb1ff | 360 | { |
b1d67693 GH |
361 | struct scsi_cmnd *cmnd = urb->context; |
362 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
e0648520 | 363 | struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; |
b1d67693 | 364 | struct scsi_data_buffer *sdb = NULL; |
e0648520 | 365 | unsigned long flags; |
b1d67693 | 366 | |
e0648520 | 367 | spin_lock_irqsave(&devinfo->lock, flags); |
b7b5d11f | 368 | |
b1d67693 GH |
369 | if (cmdinfo->data_in_urb == urb) { |
370 | sdb = scsi_in(cmnd); | |
371 | cmdinfo->state &= ~DATA_IN_URB_INFLIGHT; | |
85fea825 | 372 | cmdinfo->data_in_urb = NULL; |
b1d67693 GH |
373 | } else if (cmdinfo->data_out_urb == urb) { |
374 | sdb = scsi_out(cmnd); | |
375 | cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT; | |
85fea825 | 376 | cmdinfo->data_out_urb = NULL; |
b1d67693 | 377 | } |
f491ecbb GH |
378 | if (sdb == NULL) { |
379 | WARN_ON_ONCE(1); | |
b7b5d11f HG |
380 | goto out; |
381 | } | |
382 | ||
383 | if (devinfo->resetting) | |
384 | goto out; | |
385 | ||
d89da03a HG |
386 | /* Data urbs should not complete before the cmd urb is submitted */ |
387 | if (cmdinfo->state & SUBMIT_CMD_URB) { | |
1ad7ed5a | 388 | uas_log_cmd_state(cmnd, "unexpected data cmplt", 0); |
d89da03a HG |
389 | goto out; |
390 | } | |
391 | ||
b7b5d11f | 392 | if (urb->status) { |
1ad7ed5a HG |
393 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) |
394 | uas_log_cmd_state(cmnd, "data cmplt err", urb->status); | |
8aac863e GH |
395 | /* error: no data transfered */ |
396 | sdb->resid = sdb->length; | |
397 | } else { | |
398 | sdb->resid = sdb->length - urb->actual_length; | |
399 | } | |
b1d67693 | 400 | uas_try_complete(cmnd, __func__); |
b7b5d11f | 401 | out: |
85fea825 | 402 | usb_free_urb(urb); |
e0648520 | 403 | spin_unlock_irqrestore(&devinfo->lock, flags); |
115bb1ff MW |
404 | } |
405 | ||
876285cc HG |
406 | static void uas_cmd_cmplt(struct urb *urb) |
407 | { | |
b6823c51 HG |
408 | if (urb->status) |
409 | dev_err(&urb->dev->dev, "cmd cmplt err %d\n", urb->status); | |
876285cc | 410 | |
876285cc HG |
411 | usb_free_urb(urb); |
412 | } | |
413 | ||
115bb1ff | 414 | static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, |
b1d67693 GH |
415 | struct scsi_cmnd *cmnd, |
416 | enum dma_data_direction dir) | |
115bb1ff MW |
417 | { |
418 | struct usb_device *udev = devinfo->udev; | |
2d75b9cb | 419 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; |
115bb1ff | 420 | struct urb *urb = usb_alloc_urb(0, gfp); |
b1d67693 GH |
421 | struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE) |
422 | ? scsi_in(cmnd) : scsi_out(cmnd); | |
2d75b9cb HG |
423 | unsigned int pipe = (dir == DMA_FROM_DEVICE) |
424 | ? devinfo->data_in_pipe : devinfo->data_out_pipe; | |
115bb1ff MW |
425 | |
426 | if (!urb) | |
427 | goto out; | |
b1d67693 GH |
428 | usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, |
429 | uas_data_cmplt, cmnd); | |
2d75b9cb | 430 | urb->stream_id = cmdinfo->stream; |
115bb1ff MW |
431 | urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; |
432 | urb->sg = sdb->table.sgl; | |
433 | out: | |
434 | return urb; | |
435 | } | |
436 | ||
437 | static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, | |
2d75b9cb | 438 | struct scsi_cmnd *cmnd) |
115bb1ff MW |
439 | { |
440 | struct usb_device *udev = devinfo->udev; | |
2d75b9cb | 441 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; |
115bb1ff MW |
442 | struct urb *urb = usb_alloc_urb(0, gfp); |
443 | struct sense_iu *iu; | |
444 | ||
445 | if (!urb) | |
446 | goto out; | |
447 | ||
ac563cfd | 448 | iu = kzalloc(sizeof(*iu), gfp); |
115bb1ff MW |
449 | if (!iu) |
450 | goto free; | |
451 | ||
452 | usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), | |
2d75b9cb HG |
453 | uas_stat_cmplt, cmnd->device->host); |
454 | urb->stream_id = cmdinfo->stream; | |
115bb1ff MW |
455 | urb->transfer_flags |= URB_FREE_BUFFER; |
456 | out: | |
457 | return urb; | |
458 | free: | |
459 | usb_free_urb(urb); | |
460 | return NULL; | |
461 | } | |
462 | ||
463 | static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, | |
a887cd36 | 464 | struct scsi_cmnd *cmnd) |
115bb1ff MW |
465 | { |
466 | struct usb_device *udev = devinfo->udev; | |
467 | struct scsi_device *sdev = cmnd->device; | |
468 | struct urb *urb = usb_alloc_urb(0, gfp); | |
469 | struct command_iu *iu; | |
470 | int len; | |
471 | ||
472 | if (!urb) | |
473 | goto out; | |
474 | ||
475 | len = cmnd->cmd_len - 16; | |
476 | if (len < 0) | |
477 | len = 0; | |
478 | len = ALIGN(len, 4); | |
ac563cfd | 479 | iu = kzalloc(sizeof(*iu) + len, gfp); |
115bb1ff MW |
480 | if (!iu) |
481 | goto free; | |
482 | ||
483 | iu->iu_id = IU_ID_COMMAND; | |
e0620001 | 484 | iu->tag = cpu_to_be16(uas_get_tag(cmnd)); |
02e031cb | 485 | iu->prio_attr = UAS_SIMPLE_TAG; |
115bb1ff MW |
486 | iu->len = len; |
487 | int_to_scsilun(sdev->lun, &iu->lun); | |
488 | memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len); | |
489 | ||
490 | usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len, | |
b6823c51 | 491 | uas_cmd_cmplt, NULL); |
115bb1ff MW |
492 | urb->transfer_flags |= URB_FREE_BUFFER; |
493 | out: | |
494 | return urb; | |
495 | free: | |
496 | usb_free_urb(urb); | |
497 | return NULL; | |
498 | } | |
499 | ||
500 | /* | |
501 | * Why should I request the Status IU before sending the Command IU? Spec | |
502 | * says to, but also says the device may receive them in any order. Seems | |
503 | * daft to me. | |
504 | */ | |
505 | ||
2d75b9cb | 506 | static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) |
115bb1ff | 507 | { |
2d75b9cb | 508 | struct uas_dev_info *devinfo = cmnd->device->hostdata; |
e9bd7e1a | 509 | struct urb *urb; |
876285cc | 510 | int err; |
115bb1ff | 511 | |
2d75b9cb | 512 | urb = uas_alloc_sense_urb(devinfo, gfp, cmnd); |
e9bd7e1a | 513 | if (!urb) |
70cf0fba | 514 | return NULL; |
d5f808d3 | 515 | usb_anchor_urb(urb, &devinfo->sense_urbs); |
876285cc HG |
516 | err = usb_submit_urb(urb, gfp); |
517 | if (err) { | |
d5f808d3 | 518 | usb_unanchor_urb(urb); |
1ad7ed5a | 519 | uas_log_cmd_state(cmnd, "sense submit err", err); |
e9bd7e1a | 520 | usb_free_urb(urb); |
70cf0fba | 521 | return NULL; |
115bb1ff | 522 | } |
70cf0fba | 523 | return urb; |
e9bd7e1a GH |
524 | } |
525 | ||
526 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, | |
527 | struct uas_dev_info *devinfo, gfp_t gfp) | |
528 | { | |
529 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
70cf0fba | 530 | struct urb *urb; |
876285cc | 531 | int err; |
115bb1ff | 532 | |
ab945eff | 533 | lockdep_assert_held(&devinfo->lock); |
92a3f767 | 534 | if (cmdinfo->state & SUBMIT_STATUS_URB) { |
2d75b9cb | 535 | urb = uas_submit_sense_urb(cmnd, gfp); |
70cf0fba HG |
536 | if (!urb) |
537 | return SCSI_MLQUEUE_DEVICE_BUSY; | |
92a3f767 | 538 | cmdinfo->state &= ~SUBMIT_STATUS_URB; |
115bb1ff MW |
539 | } |
540 | ||
541 | if (cmdinfo->state & ALLOC_DATA_IN_URB) { | |
542 | cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, | |
2d75b9cb | 543 | cmnd, DMA_FROM_DEVICE); |
115bb1ff MW |
544 | if (!cmdinfo->data_in_urb) |
545 | return SCSI_MLQUEUE_DEVICE_BUSY; | |
546 | cmdinfo->state &= ~ALLOC_DATA_IN_URB; | |
547 | } | |
548 | ||
549 | if (cmdinfo->state & SUBMIT_DATA_IN_URB) { | |
d5f808d3 | 550 | usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs); |
876285cc HG |
551 | err = usb_submit_urb(cmdinfo->data_in_urb, gfp); |
552 | if (err) { | |
d5f808d3 | 553 | usb_unanchor_urb(cmdinfo->data_in_urb); |
1ad7ed5a | 554 | uas_log_cmd_state(cmnd, "data in submit err", err); |
115bb1ff MW |
555 | return SCSI_MLQUEUE_DEVICE_BUSY; |
556 | } | |
557 | cmdinfo->state &= ~SUBMIT_DATA_IN_URB; | |
b1d67693 | 558 | cmdinfo->state |= DATA_IN_URB_INFLIGHT; |
115bb1ff MW |
559 | } |
560 | ||
561 | if (cmdinfo->state & ALLOC_DATA_OUT_URB) { | |
562 | cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, | |
2d75b9cb | 563 | cmnd, DMA_TO_DEVICE); |
115bb1ff MW |
564 | if (!cmdinfo->data_out_urb) |
565 | return SCSI_MLQUEUE_DEVICE_BUSY; | |
566 | cmdinfo->state &= ~ALLOC_DATA_OUT_URB; | |
567 | } | |
568 | ||
569 | if (cmdinfo->state & SUBMIT_DATA_OUT_URB) { | |
d5f808d3 | 570 | usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs); |
876285cc HG |
571 | err = usb_submit_urb(cmdinfo->data_out_urb, gfp); |
572 | if (err) { | |
d5f808d3 | 573 | usb_unanchor_urb(cmdinfo->data_out_urb); |
1ad7ed5a | 574 | uas_log_cmd_state(cmnd, "data out submit err", err); |
115bb1ff MW |
575 | return SCSI_MLQUEUE_DEVICE_BUSY; |
576 | } | |
577 | cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; | |
b1d67693 | 578 | cmdinfo->state |= DATA_OUT_URB_INFLIGHT; |
115bb1ff MW |
579 | } |
580 | ||
581 | if (cmdinfo->state & ALLOC_CMD_URB) { | |
a887cd36 | 582 | cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd); |
115bb1ff MW |
583 | if (!cmdinfo->cmd_urb) |
584 | return SCSI_MLQUEUE_DEVICE_BUSY; | |
585 | cmdinfo->state &= ~ALLOC_CMD_URB; | |
586 | } | |
587 | ||
588 | if (cmdinfo->state & SUBMIT_CMD_URB) { | |
d5f808d3 | 589 | usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs); |
876285cc HG |
590 | err = usb_submit_urb(cmdinfo->cmd_urb, gfp); |
591 | if (err) { | |
d5f808d3 | 592 | usb_unanchor_urb(cmdinfo->cmd_urb); |
1ad7ed5a | 593 | uas_log_cmd_state(cmnd, "cmd submit err", err); |
115bb1ff MW |
594 | return SCSI_MLQUEUE_DEVICE_BUSY; |
595 | } | |
a0e39e34 | 596 | cmdinfo->cmd_urb = NULL; |
115bb1ff | 597 | cmdinfo->state &= ~SUBMIT_CMD_URB; |
b1d67693 | 598 | cmdinfo->state |= COMMAND_INFLIGHT; |
115bb1ff MW |
599 | } |
600 | ||
601 | return 0; | |
602 | } | |
603 | ||
f281233d | 604 | static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, |
115bb1ff MW |
605 | void (*done)(struct scsi_cmnd *)) |
606 | { | |
607 | struct scsi_device *sdev = cmnd->device; | |
608 | struct uas_dev_info *devinfo = sdev->hostdata; | |
609 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; | |
e0648520 | 610 | unsigned long flags; |
5e61aede | 611 | unsigned int stream; |
115bb1ff MW |
612 | int err; |
613 | ||
614 | BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); | |
615 | ||
f9dc024a HG |
616 | /* Re-check scsi_block_requests now that we've the host-lock */ |
617 | if (cmnd->device->host->host_self_blocked) | |
618 | return SCSI_MLQUEUE_DEVICE_BUSY; | |
619 | ||
59307852 HG |
620 | if ((devinfo->flags & US_FL_NO_ATA_1X) && |
621 | (cmnd->cmnd[0] == ATA_12 || cmnd->cmnd[0] == ATA_16)) { | |
622 | memcpy(cmnd->sense_buffer, usb_stor_sense_invalidCDB, | |
623 | sizeof(usb_stor_sense_invalidCDB)); | |
624 | cmnd->result = SAM_STAT_CHECK_CONDITION; | |
625 | cmnd->scsi_done(cmnd); | |
626 | return 0; | |
627 | } | |
628 | ||
c6f63207 HG |
629 | spin_lock_irqsave(&devinfo->lock, flags); |
630 | ||
f8be6bfc GH |
631 | if (devinfo->resetting) { |
632 | cmnd->result = DID_ERROR << 16; | |
633 | cmnd->scsi_done(cmnd); | |
c6f63207 | 634 | spin_unlock_irqrestore(&devinfo->lock, flags); |
f8be6bfc GH |
635 | return 0; |
636 | } | |
637 | ||
5e61aede HG |
638 | stream = uas_get_tag(cmnd); |
639 | if (devinfo->cmnd[stream - 1]) { | |
e0648520 | 640 | spin_unlock_irqrestore(&devinfo->lock, flags); |
115bb1ff | 641 | return SCSI_MLQUEUE_DEVICE_BUSY; |
e0648520 | 642 | } |
115bb1ff | 643 | |
115bb1ff MW |
644 | cmnd->scsi_done = done; |
645 | ||
5e61aede HG |
646 | memset(cmdinfo, 0, sizeof(*cmdinfo)); |
647 | cmdinfo->stream = stream; | |
e0620001 | 648 | cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB; |
115bb1ff MW |
649 | |
650 | switch (cmnd->sc_data_direction) { | |
651 | case DMA_FROM_DEVICE: | |
652 | cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; | |
653 | break; | |
654 | case DMA_BIDIRECTIONAL: | |
655 | cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; | |
656 | case DMA_TO_DEVICE: | |
657 | cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB; | |
658 | case DMA_NONE: | |
659 | break; | |
660 | } | |
661 | ||
662 | if (!devinfo->use_streams) { | |
db32de11 | 663 | cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); |
115bb1ff MW |
664 | cmdinfo->stream = 0; |
665 | } | |
666 | ||
667 | err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC); | |
668 | if (err) { | |
669 | /* If we did nothing, give up now */ | |
92a3f767 | 670 | if (cmdinfo->state & SUBMIT_STATUS_URB) { |
e0648520 | 671 | spin_unlock_irqrestore(&devinfo->lock, flags); |
115bb1ff MW |
672 | return SCSI_MLQUEUE_DEVICE_BUSY; |
673 | } | |
1bf8198e | 674 | uas_add_work(cmdinfo); |
115bb1ff MW |
675 | } |
676 | ||
5e61aede | 677 | devinfo->cmnd[stream - 1] = cmnd; |
e0648520 | 678 | spin_unlock_irqrestore(&devinfo->lock, flags); |
115bb1ff MW |
679 | return 0; |
680 | } | |
681 | ||
f281233d JG |
682 | static DEF_SCSI_QCMD(uas_queuecommand) |
683 | ||
616f0e6c HG |
684 | /* |
685 | * For now we do not support actually sending an abort to the device, so | |
686 | * this eh always fails. Still we must define it to make sure that we've | |
687 | * dropped all references to the cmnd in question once this function exits. | |
688 | */ | |
689 | static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) | |
115bb1ff | 690 | { |
616f0e6c HG |
691 | struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; |
692 | struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; | |
693 | struct urb *data_in_urb = NULL; | |
694 | struct urb *data_out_urb = NULL; | |
e0648520 | 695 | unsigned long flags; |
115bb1ff | 696 | |
e0648520 | 697 | spin_lock_irqsave(&devinfo->lock, flags); |
b83b86a3 | 698 | |
1ad7ed5a | 699 | uas_log_cmd_state(cmnd, __func__, 0); |
c6f63207 | 700 | |
616f0e6c HG |
701 | /* Ensure that try_complete does not call scsi_done */ |
702 | cmdinfo->state |= COMMAND_ABORTED; | |
b83b86a3 | 703 | |
616f0e6c HG |
704 | /* Drop all refs to this cmnd, kill data urbs to break their ref */ |
705 | devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL; | |
706 | if (cmdinfo->state & DATA_IN_URB_INFLIGHT) | |
707 | data_in_urb = usb_get_urb(cmdinfo->data_in_urb); | |
708 | if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) | |
709 | data_out_urb = usb_get_urb(cmdinfo->data_out_urb); | |
e0648520 | 710 | |
4c5481ef | 711 | uas_free_unsubmitted_urbs(cmnd); |
b83b86a3 | 712 | |
b83b86a3 HG |
713 | spin_unlock_irqrestore(&devinfo->lock, flags); |
714 | ||
616f0e6c HG |
715 | if (data_in_urb) { |
716 | usb_kill_urb(data_in_urb); | |
717 | usb_put_urb(data_in_urb); | |
c6f63207 | 718 | } |
616f0e6c HG |
719 | if (data_out_urb) { |
720 | usb_kill_urb(data_out_urb); | |
721 | usb_put_urb(data_out_urb); | |
5d390403 | 722 | } |
115bb1ff | 723 | |
616f0e6c | 724 | return FAILED; |
115bb1ff MW |
725 | } |
726 | ||
727 | static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) | |
728 | { | |
729 | struct scsi_device *sdev = cmnd->device; | |
730 | struct uas_dev_info *devinfo = sdev->hostdata; | |
731 | struct usb_device *udev = devinfo->udev; | |
b7b5d11f | 732 | unsigned long flags; |
023b515e | 733 | int err; |
115bb1ff | 734 | |
be326f4c HG |
735 | err = usb_lock_device_for_reset(udev, devinfo->intf); |
736 | if (err) { | |
737 | shost_printk(KERN_ERR, sdev->host, | |
738 | "%s FAILED to get lock err %d\n", __func__, err); | |
739 | return FAILED; | |
740 | } | |
741 | ||
326349f8 | 742 | shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__); |
b7b5d11f HG |
743 | |
744 | spin_lock_irqsave(&devinfo->lock, flags); | |
023b515e | 745 | devinfo->resetting = 1; |
b7b5d11f HG |
746 | spin_unlock_irqrestore(&devinfo->lock, flags); |
747 | ||
a0e39e34 | 748 | usb_kill_anchored_urbs(&devinfo->cmd_urbs); |
023b515e GH |
749 | usb_kill_anchored_urbs(&devinfo->sense_urbs); |
750 | usb_kill_anchored_urbs(&devinfo->data_urbs); | |
1589349f HG |
751 | uas_zap_pending(devinfo, DID_RESET); |
752 | ||
023b515e | 753 | err = usb_reset_device(udev); |
b7b5d11f HG |
754 | |
755 | spin_lock_irqsave(&devinfo->lock, flags); | |
023b515e | 756 | devinfo->resetting = 0; |
b7b5d11f | 757 | spin_unlock_irqrestore(&devinfo->lock, flags); |
115bb1ff | 758 | |
be326f4c HG |
759 | usb_unlock_device(udev); |
760 | ||
023b515e | 761 | if (err) { |
ce39fe6f HG |
762 | shost_printk(KERN_INFO, sdev->host, "%s FAILED err %d\n", |
763 | __func__, err); | |
023b515e GH |
764 | return FAILED; |
765 | } | |
115bb1ff | 766 | |
023b515e GH |
767 | shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__); |
768 | return SUCCESS; | |
115bb1ff MW |
769 | } |
770 | ||
771 | static int uas_slave_alloc(struct scsi_device *sdev) | |
772 | { | |
21fc05b6 | 773 | sdev->hostdata = (void *)sdev->host->hostdata; |
37599f96 HG |
774 | |
775 | /* USB has unusual DMA-alignment requirements: Although the | |
776 | * starting address of each scatter-gather element doesn't matter, | |
777 | * the length of each element except the last must be divisible | |
778 | * by the Bulk maxpacket value. There's currently no way to | |
779 | * express this by block-layer constraints, so we'll cop out | |
780 | * and simply require addresses to be aligned at 512-byte | |
781 | * boundaries. This is okay since most block I/O involves | |
782 | * hardware sectors that are multiples of 512 bytes in length, | |
783 | * and since host controllers up through USB 2.0 have maxpacket | |
784 | * values no larger than 512. | |
785 | * | |
786 | * But it doesn't suffice for Wireless USB, where Bulk maxpacket | |
787 | * values can be as large as 2048. To make that work properly | |
788 | * will require changes to the block layer. | |
789 | */ | |
790 | blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); | |
791 | ||
115bb1ff MW |
792 | return 0; |
793 | } | |
794 | ||
795 | static int uas_slave_configure(struct scsi_device *sdev) | |
796 | { | |
797 | struct uas_dev_info *devinfo = sdev->hostdata; | |
734016b0 HG |
798 | |
799 | if (devinfo->flags & US_FL_NO_REPORT_OPCODES) | |
800 | sdev->no_report_opcodes = 1; | |
801 | ||
115bb1ff | 802 | scsi_set_tag_type(sdev, MSG_ORDERED_TAG); |
d3f7c156 | 803 | scsi_activate_tcq(sdev, devinfo->qdepth - 2); |
115bb1ff MW |
804 | return 0; |
805 | } | |
806 | ||
807 | static struct scsi_host_template uas_host_template = { | |
808 | .module = THIS_MODULE, | |
809 | .name = "uas", | |
810 | .queuecommand = uas_queuecommand, | |
811 | .slave_alloc = uas_slave_alloc, | |
812 | .slave_configure = uas_slave_configure, | |
813 | .eh_abort_handler = uas_eh_abort_handler, | |
115bb1ff MW |
814 | .eh_bus_reset_handler = uas_eh_bus_reset_handler, |
815 | .can_queue = 65536, /* Is there a limit on the _host_ ? */ | |
816 | .this_id = -1, | |
817 | .sg_tablesize = SG_NONE, | |
818 | .cmd_per_lun = 1, /* until we override it */ | |
819 | .skip_settle_delay = 1, | |
820 | .ordered_tag = 1, | |
2c2d831c CH |
821 | |
822 | /* | |
823 | * The uas drivers expects tags not to be bigger than the maximum | |
824 | * per-device queue depth, which is not true with the blk-mq tag | |
825 | * allocator. | |
826 | */ | |
827 | .disable_blk_mq = true, | |
115bb1ff MW |
828 | }; |
829 | ||
79b4c061 HG |
830 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ |
831 | vendorName, productName, useProtocol, useTransport, \ | |
832 | initFunction, flags) \ | |
833 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ | |
834 | .driver_info = (flags) } | |
835 | ||
115bb1ff | 836 | static struct usb_device_id uas_usb_ids[] = { |
79b4c061 | 837 | # include "unusual_uas.h" |
115bb1ff MW |
838 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, |
839 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) }, | |
115bb1ff MW |
840 | { } |
841 | }; | |
842 | MODULE_DEVICE_TABLE(usb, uas_usb_ids); | |
843 | ||
79b4c061 HG |
844 | #undef UNUSUAL_DEV |
845 | ||
e1be067b HG |
846 | static int uas_switch_interface(struct usb_device *udev, |
847 | struct usb_interface *intf) | |
848 | { | |
849 | int alt; | |
850 | ||
851 | alt = uas_find_uas_alt_setting(intf); | |
852 | if (alt < 0) | |
853 | return alt; | |
854 | ||
855 | return usb_set_interface(udev, | |
856 | intf->altsetting[0].desc.bInterfaceNumber, alt); | |
857 | } | |
858 | ||
58d51444 | 859 | static int uas_configure_endpoints(struct uas_dev_info *devinfo) |
34f11e59 HG |
860 | { |
861 | struct usb_host_endpoint *eps[4] = { }; | |
862 | struct usb_device *udev = devinfo->udev; | |
863 | int r; | |
864 | ||
34f11e59 | 865 | r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps); |
74d71aec HG |
866 | if (r) |
867 | return r; | |
868 | ||
869 | devinfo->cmd_pipe = usb_sndbulkpipe(udev, | |
870 | usb_endpoint_num(&eps[0]->desc)); | |
871 | devinfo->status_pipe = usb_rcvbulkpipe(udev, | |
872 | usb_endpoint_num(&eps[1]->desc)); | |
873 | devinfo->data_in_pipe = usb_rcvbulkpipe(udev, | |
874 | usb_endpoint_num(&eps[2]->desc)); | |
875 | devinfo->data_out_pipe = usb_sndbulkpipe(udev, | |
876 | usb_endpoint_num(&eps[3]->desc)); | |
115bb1ff | 877 | |
e5e55819 | 878 | if (udev->speed < USB_SPEED_SUPER) { |
e2875c33 | 879 | devinfo->qdepth = 32; |
115bb1ff MW |
880 | devinfo->use_streams = 0; |
881 | } else { | |
58d51444 | 882 | devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, |
5e61aede | 883 | 3, MAX_CMNDS, GFP_NOIO); |
58d51444 HG |
884 | if (devinfo->qdepth < 0) |
885 | return devinfo->qdepth; | |
115bb1ff MW |
886 | devinfo->use_streams = 1; |
887 | } | |
58d51444 HG |
888 | |
889 | return 0; | |
115bb1ff MW |
890 | } |
891 | ||
dae51546 SAS |
892 | static void uas_free_streams(struct uas_dev_info *devinfo) |
893 | { | |
894 | struct usb_device *udev = devinfo->udev; | |
895 | struct usb_host_endpoint *eps[3]; | |
896 | ||
897 | eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); | |
898 | eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); | |
899 | eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); | |
94d72f00 | 900 | usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO); |
dae51546 SAS |
901 | } |
902 | ||
115bb1ff MW |
903 | static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) |
904 | { | |
6ce8213b HG |
905 | int result = -ENOMEM; |
906 | struct Scsi_Host *shost = NULL; | |
115bb1ff MW |
907 | struct uas_dev_info *devinfo; |
908 | struct usb_device *udev = interface_to_usbdev(intf); | |
909 | ||
79b4c061 HG |
910 | if (!uas_use_uas_driver(intf, id)) |
911 | return -ENODEV; | |
912 | ||
89dc2905 MW |
913 | if (uas_switch_interface(udev, intf)) |
914 | return -ENODEV; | |
115bb1ff | 915 | |
21fc05b6 HG |
916 | shost = scsi_host_alloc(&uas_host_template, |
917 | sizeof(struct uas_dev_info)); | |
115bb1ff | 918 | if (!shost) |
6ce8213b | 919 | goto set_alt0; |
115bb1ff MW |
920 | |
921 | shost->max_cmd_len = 16 + 252; | |
922 | shost->max_id = 1; | |
bde027b4 GH |
923 | shost->max_lun = 256; |
924 | shost->max_channel = 0; | |
115bb1ff MW |
925 | shost->sg_tablesize = udev->bus->sg_tablesize; |
926 | ||
21fc05b6 | 927 | devinfo = (struct uas_dev_info *)shost->hostdata; |
115bb1ff MW |
928 | devinfo->intf = intf; |
929 | devinfo->udev = udev; | |
023b515e | 930 | devinfo->resetting = 0; |
da65c2bb | 931 | devinfo->shutdown = 0; |
59307852 HG |
932 | devinfo->flags = id->driver_info; |
933 | usb_stor_adjust_quirks(udev, &devinfo->flags); | |
a0e39e34 | 934 | init_usb_anchor(&devinfo->cmd_urbs); |
bdd000fb GH |
935 | init_usb_anchor(&devinfo->sense_urbs); |
936 | init_usb_anchor(&devinfo->data_urbs); | |
e0648520 | 937 | spin_lock_init(&devinfo->lock); |
1bf8198e | 938 | INIT_WORK(&devinfo->work, uas_do_work); |
58d51444 HG |
939 | |
940 | result = uas_configure_endpoints(devinfo); | |
941 | if (result) | |
942 | goto set_alt0; | |
115bb1ff | 943 | |
d3f7c156 | 944 | result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); |
115bb1ff | 945 | if (result) |
6ce8213b | 946 | goto free_streams; |
dae51546 | 947 | |
c637f1fa | 948 | usb_set_intfdata(intf, shost); |
dae51546 SAS |
949 | result = scsi_add_host(shost, &intf->dev); |
950 | if (result) | |
6ce8213b | 951 | goto free_streams; |
dae51546 | 952 | |
115bb1ff | 953 | scsi_scan_host(shost); |
115bb1ff | 954 | return result; |
dae51546 | 955 | |
6ce8213b | 956 | free_streams: |
dae51546 | 957 | uas_free_streams(devinfo); |
c637f1fa | 958 | usb_set_intfdata(intf, NULL); |
6ce8213b HG |
959 | set_alt0: |
960 | usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); | |
115bb1ff MW |
961 | if (shost) |
962 | scsi_host_put(shost); | |
963 | return result; | |
964 | } | |
965 | ||
f9dc024a HG |
966 | static int uas_cmnd_list_empty(struct uas_dev_info *devinfo) |
967 | { | |
968 | unsigned long flags; | |
969 | int i, r = 1; | |
970 | ||
971 | spin_lock_irqsave(&devinfo->lock, flags); | |
972 | ||
973 | for (i = 0; i < devinfo->qdepth; i++) { | |
974 | if (devinfo->cmnd[i]) { | |
975 | r = 0; /* Not empty */ | |
976 | break; | |
977 | } | |
978 | } | |
979 | ||
980 | spin_unlock_irqrestore(&devinfo->lock, flags); | |
981 | ||
982 | return r; | |
983 | } | |
984 | ||
985 | /* | |
986 | * Wait for any pending cmnds to complete, on usb-2 sense_urbs may temporarily | |
987 | * get empty while there still is more work to do due to sense-urbs completing | |
988 | * with a READ/WRITE_READY iu code, so keep waiting until the list gets empty. | |
989 | */ | |
990 | static int uas_wait_for_pending_cmnds(struct uas_dev_info *devinfo) | |
991 | { | |
992 | unsigned long start_time; | |
993 | int r; | |
994 | ||
995 | start_time = jiffies; | |
996 | do { | |
997 | flush_work(&devinfo->work); | |
998 | ||
999 | r = usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000); | |
1000 | if (r == 0) | |
1001 | return -ETIME; | |
1002 | ||
1003 | r = usb_wait_anchor_empty_timeout(&devinfo->data_urbs, 500); | |
1004 | if (r == 0) | |
1005 | return -ETIME; | |
1006 | ||
1007 | if (time_after(jiffies, start_time + 5 * HZ)) | |
1008 | return -ETIME; | |
1009 | } while (!uas_cmnd_list_empty(devinfo)); | |
1010 | ||
1011 | return 0; | |
1012 | } | |
1013 | ||
115bb1ff MW |
1014 | static int uas_pre_reset(struct usb_interface *intf) |
1015 | { | |
4de7a373 | 1016 | struct Scsi_Host *shost = usb_get_intfdata(intf); |
21fc05b6 | 1017 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
4de7a373 HG |
1018 | unsigned long flags; |
1019 | ||
da65c2bb HG |
1020 | if (devinfo->shutdown) |
1021 | return 0; | |
1022 | ||
4de7a373 HG |
1023 | /* Block new requests */ |
1024 | spin_lock_irqsave(shost->host_lock, flags); | |
1025 | scsi_block_requests(shost); | |
1026 | spin_unlock_irqrestore(shost->host_lock, flags); | |
1027 | ||
f9dc024a | 1028 | if (uas_wait_for_pending_cmnds(devinfo) != 0) { |
4de7a373 | 1029 | shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__); |
f9dc024a | 1030 | scsi_unblock_requests(shost); |
4de7a373 HG |
1031 | return 1; |
1032 | } | |
1033 | ||
1034 | uas_free_streams(devinfo); | |
1035 | ||
115bb1ff MW |
1036 | return 0; |
1037 | } | |
1038 | ||
1039 | static int uas_post_reset(struct usb_interface *intf) | |
1040 | { | |
4de7a373 | 1041 | struct Scsi_Host *shost = usb_get_intfdata(intf); |
21fc05b6 | 1042 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
4de7a373 | 1043 | unsigned long flags; |
ce39fe6f | 1044 | int err; |
4de7a373 | 1045 | |
da65c2bb HG |
1046 | if (devinfo->shutdown) |
1047 | return 0; | |
1048 | ||
ce39fe6f HG |
1049 | err = uas_configure_endpoints(devinfo); |
1050 | if (err) { | |
58d51444 | 1051 | shost_printk(KERN_ERR, shost, |
ce39fe6f HG |
1052 | "%s: alloc streams error %d after reset", |
1053 | __func__, err); | |
58d51444 HG |
1054 | return 1; |
1055 | } | |
4de7a373 HG |
1056 | |
1057 | spin_lock_irqsave(shost->host_lock, flags); | |
1058 | scsi_report_bus_reset(shost, 0); | |
1059 | spin_unlock_irqrestore(shost->host_lock, flags); | |
1060 | ||
1061 | scsi_unblock_requests(shost); | |
1062 | ||
115bb1ff MW |
1063 | return 0; |
1064 | } | |
1065 | ||
0df1f663 HG |
1066 | static int uas_suspend(struct usb_interface *intf, pm_message_t message) |
1067 | { | |
1068 | struct Scsi_Host *shost = usb_get_intfdata(intf); | |
21fc05b6 | 1069 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
0df1f663 | 1070 | |
f9dc024a | 1071 | if (uas_wait_for_pending_cmnds(devinfo) != 0) { |
0df1f663 HG |
1072 | shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__); |
1073 | return -ETIME; | |
1074 | } | |
1075 | ||
1076 | return 0; | |
1077 | } | |
1078 | ||
1079 | static int uas_resume(struct usb_interface *intf) | |
1080 | { | |
1081 | return 0; | |
1082 | } | |
1083 | ||
1084 | static int uas_reset_resume(struct usb_interface *intf) | |
1085 | { | |
1086 | struct Scsi_Host *shost = usb_get_intfdata(intf); | |
21fc05b6 | 1087 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
0df1f663 | 1088 | unsigned long flags; |
ce39fe6f | 1089 | int err; |
0df1f663 | 1090 | |
ce39fe6f HG |
1091 | err = uas_configure_endpoints(devinfo); |
1092 | if (err) { | |
0df1f663 | 1093 | shost_printk(KERN_ERR, shost, |
ce39fe6f HG |
1094 | "%s: alloc streams error %d after reset", |
1095 | __func__, err); | |
0df1f663 HG |
1096 | return -EIO; |
1097 | } | |
1098 | ||
1099 | spin_lock_irqsave(shost->host_lock, flags); | |
1100 | scsi_report_bus_reset(shost, 0); | |
1101 | spin_unlock_irqrestore(shost->host_lock, flags); | |
1102 | ||
1103 | return 0; | |
1104 | } | |
1105 | ||
115bb1ff MW |
1106 | static void uas_disconnect(struct usb_interface *intf) |
1107 | { | |
115bb1ff | 1108 | struct Scsi_Host *shost = usb_get_intfdata(intf); |
21fc05b6 | 1109 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
b7b5d11f | 1110 | unsigned long flags; |
115bb1ff | 1111 | |
b7b5d11f | 1112 | spin_lock_irqsave(&devinfo->lock, flags); |
4c456971 | 1113 | devinfo->resetting = 1; |
b7b5d11f HG |
1114 | spin_unlock_irqrestore(&devinfo->lock, flags); |
1115 | ||
1bf8198e | 1116 | cancel_work_sync(&devinfo->work); |
a0e39e34 | 1117 | usb_kill_anchored_urbs(&devinfo->cmd_urbs); |
bdd000fb GH |
1118 | usb_kill_anchored_urbs(&devinfo->sense_urbs); |
1119 | usb_kill_anchored_urbs(&devinfo->data_urbs); | |
1589349f HG |
1120 | uas_zap_pending(devinfo, DID_NO_CONNECT); |
1121 | ||
4c456971 | 1122 | scsi_remove_host(shost); |
dae51546 | 1123 | uas_free_streams(devinfo); |
21fc05b6 | 1124 | scsi_host_put(shost); |
115bb1ff MW |
1125 | } |
1126 | ||
da65c2bb HG |
1127 | /* |
1128 | * Put the device back in usb-storage mode on shutdown, as some BIOS-es | |
1129 | * hang on reboot when the device is still in uas mode. Note the reset is | |
1130 | * necessary as some devices won't revert to usb-storage mode without it. | |
1131 | */ | |
1132 | static void uas_shutdown(struct device *dev) | |
1133 | { | |
1134 | struct usb_interface *intf = to_usb_interface(dev); | |
1135 | struct usb_device *udev = interface_to_usbdev(intf); | |
1136 | struct Scsi_Host *shost = usb_get_intfdata(intf); | |
21fc05b6 | 1137 | struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; |
da65c2bb HG |
1138 | |
1139 | if (system_state != SYSTEM_RESTART) | |
1140 | return; | |
1141 | ||
1142 | devinfo->shutdown = 1; | |
1143 | uas_free_streams(devinfo); | |
1144 | usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); | |
1145 | usb_reset_device(udev); | |
1146 | } | |
1147 | ||
115bb1ff MW |
1148 | static struct usb_driver uas_driver = { |
1149 | .name = "uas", | |
1150 | .probe = uas_probe, | |
1151 | .disconnect = uas_disconnect, | |
1152 | .pre_reset = uas_pre_reset, | |
1153 | .post_reset = uas_post_reset, | |
0df1f663 HG |
1154 | .suspend = uas_suspend, |
1155 | .resume = uas_resume, | |
1156 | .reset_resume = uas_reset_resume, | |
da65c2bb | 1157 | .drvwrap.driver.shutdown = uas_shutdown, |
115bb1ff MW |
1158 | .id_table = uas_usb_ids, |
1159 | }; | |
1160 | ||
65db4305 | 1161 | module_usb_driver(uas_driver); |
115bb1ff MW |
1162 | |
1163 | MODULE_LICENSE("GPL"); | |
f50a4968 HG |
1164 | MODULE_AUTHOR( |
1165 | "Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp"); |