blob: 36279a46fd27021bfa58a0d30237fc1cb2991ecd [file] [log] [blame]
Matthew Wilcox115bb1f2010-10-07 13:05:23 +02001/*
2 * USB Attached SCSI
3 * Note that this is not the same as the USB Mass Storage driver
4 *
5 * Copyright Matthew Wilcox for Intel Corp, 2010
6 * Copyright Sarah Sharp for Intel Corp, 2010
7 *
8 * Distributed under the terms of the GNU GPL, version two.
9 */
10
11#include <linux/blkdev.h>
12#include <linux/slab.h>
13#include <linux/types.h>
Paul Gortmaker6eb0de82011-07-03 16:09:31 -040014#include <linux/module.h>
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020015#include <linux/usb.h>
Sebastian Andrzej Siewiorc898add2012-01-11 12:42:32 +010016#include <linux/usb/hcd.h>
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020017#include <linux/usb/storage.h>
Sebastian Andrzej Siewior348748b2012-01-11 12:45:56 +010018#include <linux/usb/uas.h>
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020019
20#include <scsi/scsi.h>
21#include <scsi/scsi_dbg.h>
22#include <scsi/scsi_cmnd.h>
23#include <scsi/scsi_device.h>
24#include <scsi/scsi_host.h>
25#include <scsi/scsi_tcq.h>
26
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020027/*
28 * The r00-r01c specs define this version of the SENSE IU data structure.
29 * It's still in use by several different firmware releases.
30 */
31struct sense_iu_old {
32 __u8 iu_id;
33 __u8 rsvd1;
34 __be16 tag;
35 __be16 len;
36 __u8 status;
37 __u8 service_response;
38 __u8 sense[SCSI_SENSE_BUFFERSIZE];
39};
40
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020041struct uas_dev_info {
42 struct usb_interface *intf;
43 struct usb_device *udev;
44 int qdepth;
45 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
46 unsigned use_streams:1;
47 unsigned uas_sense_old:1;
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +010048 struct scsi_cmnd *cmnd;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020049};
50
51enum {
Matthew Wilcox92a3f762010-12-15 15:44:04 -050052 ALLOC_STATUS_URB = (1 << 0),
53 SUBMIT_STATUS_URB = (1 << 1),
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020054 ALLOC_DATA_IN_URB = (1 << 2),
55 SUBMIT_DATA_IN_URB = (1 << 3),
56 ALLOC_DATA_OUT_URB = (1 << 4),
57 SUBMIT_DATA_OUT_URB = (1 << 5),
58 ALLOC_CMD_URB = (1 << 6),
59 SUBMIT_CMD_URB = (1 << 7),
60};
61
62/* Overrides scsi_pointer */
63struct uas_cmd_info {
64 unsigned int state;
65 unsigned int stream;
66 struct urb *cmd_urb;
Matthew Wilcox92a3f762010-12-15 15:44:04 -050067 struct urb *status_urb;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020068 struct urb *data_in_urb;
69 struct urb *data_out_urb;
70 struct list_head list;
71};
72
73/* I hate forward declarations, but I actually have a loop */
74static int uas_submit_urbs(struct scsi_cmnd *cmnd,
75 struct uas_dev_info *devinfo, gfp_t gfp);
Sarah Sharpea9da1c2011-12-02 11:55:44 -080076static void uas_do_work(struct work_struct *work);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020077
Sarah Sharpea9da1c2011-12-02 11:55:44 -080078static DECLARE_WORK(uas_work, uas_do_work);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020079static DEFINE_SPINLOCK(uas_work_lock);
80static LIST_HEAD(uas_work_list);
81
82static void uas_do_work(struct work_struct *work)
83{
84 struct uas_cmd_info *cmdinfo;
Sarah Sharpea9da1c2011-12-02 11:55:44 -080085 struct uas_cmd_info *temp;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020086 struct list_head list;
Sarah Sharpea9da1c2011-12-02 11:55:44 -080087 int err;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020088
89 spin_lock_irq(&uas_work_lock);
90 list_replace_init(&uas_work_list, &list);
91 spin_unlock_irq(&uas_work_lock);
92
Sarah Sharpea9da1c2011-12-02 11:55:44 -080093 list_for_each_entry_safe(cmdinfo, temp, &list, list) {
Matthew Wilcox115bb1f2010-10-07 13:05:23 +020094 struct scsi_pointer *scp = (void *)cmdinfo;
95 struct scsi_cmnd *cmnd = container_of(scp,
96 struct scsi_cmnd, SCp);
Sarah Sharpea9da1c2011-12-02 11:55:44 -080097 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
98 if (err) {
99 list_del(&cmdinfo->list);
100 spin_lock_irq(&uas_work_lock);
101 list_add_tail(&cmdinfo->list, &uas_work_list);
102 spin_unlock_irq(&uas_work_lock);
103 schedule_work(&uas_work);
104 }
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200105 }
106}
107
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200108static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
109{
110 struct sense_iu *sense_iu = urb->transfer_buffer;
111 struct scsi_device *sdev = cmnd->device;
112
113 if (urb->actual_length > 16) {
114 unsigned len = be16_to_cpup(&sense_iu->len);
115 if (len + 16 != urb->actual_length) {
116 int newlen = min(len + 16, urb->actual_length) - 16;
117 if (newlen < 0)
118 newlen = 0;
119 sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
120 "disagrees with IU sense data length %d, "
121 "using %d bytes of sense data\n", __func__,
122 urb->actual_length, len, newlen);
123 len = newlen;
124 }
125 memcpy(cmnd->sense_buffer, sense_iu->sense, len);
126 }
127
128 cmnd->result = sense_iu->status;
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200129 cmnd->scsi_done(cmnd);
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200130 usb_free_urb(urb);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200131}
132
133static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
134{
135 struct sense_iu_old *sense_iu = urb->transfer_buffer;
136 struct scsi_device *sdev = cmnd->device;
137
138 if (urb->actual_length > 8) {
139 unsigned len = be16_to_cpup(&sense_iu->len) - 2;
140 if (len + 8 != urb->actual_length) {
141 int newlen = min(len + 8, urb->actual_length) - 8;
142 if (newlen < 0)
143 newlen = 0;
144 sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
145 "disagrees with IU sense data length %d, "
146 "using %d bytes of sense data\n", __func__,
147 urb->actual_length, len, newlen);
148 len = newlen;
149 }
150 memcpy(cmnd->sense_buffer, sense_iu->sense, len);
151 }
152
153 cmnd->result = sense_iu->status;
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200154 cmnd->scsi_done(cmnd);
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200155 usb_free_urb(urb);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200156}
157
158static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
159 unsigned direction)
160{
161 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
162 int err;
163
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200164 cmdinfo->state = direction | SUBMIT_STATUS_URB;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200165 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
166 if (err) {
167 spin_lock(&uas_work_lock);
168 list_add_tail(&cmdinfo->list, &uas_work_list);
169 spin_unlock(&uas_work_lock);
170 schedule_work(&uas_work);
171 }
172}
173
174static void uas_stat_cmplt(struct urb *urb)
175{
176 struct iu *iu = urb->transfer_buffer;
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100177 struct Scsi_Host *shost = urb->context;
178 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200179 struct scsi_cmnd *cmnd;
180 u16 tag;
181
182 if (urb->status) {
183 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200184 usb_free_urb(urb);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200185 return;
186 }
187
188 tag = be16_to_cpup(&iu->tag) - 1;
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100189 if (tag == 0)
190 cmnd = devinfo->cmnd;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200191 else
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100192 cmnd = scsi_host_find_tag(shost, tag - 1);
Sarah Sharp96c1eb92011-12-02 11:55:48 -0800193 if (!cmnd) {
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200194 usb_free_urb(urb);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200195 return;
Sarah Sharp96c1eb92011-12-02 11:55:48 -0800196 }
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200197
198 switch (iu->iu_id) {
199 case IU_ID_STATUS:
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100200 if (devinfo->cmnd == cmnd)
201 devinfo->cmnd = NULL;
202
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200203 if (urb->actual_length < 16)
204 devinfo->uas_sense_old = 1;
205 if (devinfo->uas_sense_old)
206 uas_sense_old(urb, cmnd);
207 else
208 uas_sense(urb, cmnd);
209 break;
210 case IU_ID_READ_READY:
211 uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
212 break;
213 case IU_ID_WRITE_READY:
214 uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
215 break;
216 default:
217 scmd_printk(KERN_ERR, cmnd,
218 "Bogus IU (%d) received on status pipe\n", iu->iu_id);
219 }
220}
221
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200222static void uas_data_cmplt(struct urb *urb)
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200223{
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200224 struct scsi_data_buffer *sdb = urb->context;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200225 sdb->resid = sdb->length - urb->actual_length;
226 usb_free_urb(urb);
227}
228
229static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200230 unsigned int pipe, u16 stream_id,
231 struct scsi_data_buffer *sdb,
232 enum dma_data_direction dir)
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200233{
234 struct usb_device *udev = devinfo->udev;
235 struct urb *urb = usb_alloc_urb(0, gfp);
236
237 if (!urb)
238 goto out;
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200239 usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
240 sdb);
241 if (devinfo->use_streams)
242 urb->stream_id = stream_id;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200243 urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
244 urb->sg = sdb->table.sgl;
245 out:
246 return urb;
247}
248
249static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200250 struct scsi_cmnd *cmnd, u16 stream_id)
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200251{
252 struct usb_device *udev = devinfo->udev;
253 struct urb *urb = usb_alloc_urb(0, gfp);
254 struct sense_iu *iu;
255
256 if (!urb)
257 goto out;
258
Matthew Wilcoxac563cf2010-12-15 15:44:03 -0500259 iu = kzalloc(sizeof(*iu), gfp);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200260 if (!iu)
261 goto free;
262
263 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200264 uas_stat_cmplt, cmnd->device->host);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200265 urb->stream_id = stream_id;
266 urb->transfer_flags |= URB_FREE_BUFFER;
267 out:
268 return urb;
269 free:
270 usb_free_urb(urb);
271 return NULL;
272}
273
274static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
275 struct scsi_cmnd *cmnd, u16 stream_id)
276{
277 struct usb_device *udev = devinfo->udev;
278 struct scsi_device *sdev = cmnd->device;
279 struct urb *urb = usb_alloc_urb(0, gfp);
280 struct command_iu *iu;
281 int len;
282
283 if (!urb)
284 goto out;
285
286 len = cmnd->cmd_len - 16;
287 if (len < 0)
288 len = 0;
289 len = ALIGN(len, 4);
Matthew Wilcoxac563cf2010-12-15 15:44:03 -0500290 iu = kzalloc(sizeof(*iu) + len, gfp);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200291 if (!iu)
292 goto free;
293
294 iu->iu_id = IU_ID_COMMAND;
Sarah Sharp9eb44542011-12-02 11:55:46 -0800295 if (blk_rq_tagged(cmnd->request))
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100296 iu->tag = cpu_to_be16(cmnd->request->tag + 2);
Sarah Sharp9eb44542011-12-02 11:55:46 -0800297 else
298 iu->tag = cpu_to_be16(1);
Christoph Hellwig02e031c2010-11-10 14:54:09 +0100299 iu->prio_attr = UAS_SIMPLE_TAG;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200300 iu->len = len;
301 int_to_scsilun(sdev->lun, &iu->lun);
302 memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
303
304 usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
305 usb_free_urb, NULL);
306 urb->transfer_flags |= URB_FREE_BUFFER;
307 out:
308 return urb;
309 free:
310 usb_free_urb(urb);
311 return NULL;
312}
313
314/*
315 * Why should I request the Status IU before sending the Command IU? Spec
316 * says to, but also says the device may receive them in any order. Seems
317 * daft to me.
318 */
319
320static int uas_submit_urbs(struct scsi_cmnd *cmnd,
321 struct uas_dev_info *devinfo, gfp_t gfp)
322{
323 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
324
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500325 if (cmdinfo->state & ALLOC_STATUS_URB) {
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200326 cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
327 cmdinfo->stream);
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500328 if (!cmdinfo->status_urb)
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200329 return SCSI_MLQUEUE_DEVICE_BUSY;
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500330 cmdinfo->state &= ~ALLOC_STATUS_URB;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200331 }
332
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500333 if (cmdinfo->state & SUBMIT_STATUS_URB) {
334 if (usb_submit_urb(cmdinfo->status_urb, gfp)) {
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200335 scmd_printk(KERN_INFO, cmnd,
336 "sense urb submission failure\n");
337 return SCSI_MLQUEUE_DEVICE_BUSY;
338 }
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500339 cmdinfo->state &= ~SUBMIT_STATUS_URB;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200340 }
341
342 if (cmdinfo->state & ALLOC_DATA_IN_URB) {
343 cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200344 devinfo->data_in_pipe, cmdinfo->stream,
345 scsi_in(cmnd), DMA_FROM_DEVICE);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200346 if (!cmdinfo->data_in_urb)
347 return SCSI_MLQUEUE_DEVICE_BUSY;
348 cmdinfo->state &= ~ALLOC_DATA_IN_URB;
349 }
350
351 if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
352 if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
353 scmd_printk(KERN_INFO, cmnd,
354 "data in urb submission failure\n");
355 return SCSI_MLQUEUE_DEVICE_BUSY;
356 }
357 cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
358 }
359
360 if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
361 cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
Gerd Hoffmannc621a812012-06-19 09:54:48 +0200362 devinfo->data_out_pipe, cmdinfo->stream,
363 scsi_out(cmnd), DMA_TO_DEVICE);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200364 if (!cmdinfo->data_out_urb)
365 return SCSI_MLQUEUE_DEVICE_BUSY;
366 cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
367 }
368
369 if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
370 if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
371 scmd_printk(KERN_INFO, cmnd,
372 "data out urb submission failure\n");
373 return SCSI_MLQUEUE_DEVICE_BUSY;
374 }
375 cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
376 }
377
378 if (cmdinfo->state & ALLOC_CMD_URB) {
379 cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
380 cmdinfo->stream);
381 if (!cmdinfo->cmd_urb)
382 return SCSI_MLQUEUE_DEVICE_BUSY;
383 cmdinfo->state &= ~ALLOC_CMD_URB;
384 }
385
386 if (cmdinfo->state & SUBMIT_CMD_URB) {
387 if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
388 scmd_printk(KERN_INFO, cmnd,
389 "cmd urb submission failure\n");
390 return SCSI_MLQUEUE_DEVICE_BUSY;
391 }
392 cmdinfo->state &= ~SUBMIT_CMD_URB;
393 }
394
395 return 0;
396}
397
Jeff Garzikf2812332010-11-16 02:10:29 -0500398static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200399 void (*done)(struct scsi_cmnd *))
400{
401 struct scsi_device *sdev = cmnd->device;
402 struct uas_dev_info *devinfo = sdev->hostdata;
403 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
404 int err;
405
406 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
407
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100408 if (devinfo->cmnd)
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200409 return SCSI_MLQUEUE_DEVICE_BUSY;
410
411 if (blk_rq_tagged(cmnd->request)) {
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100412 cmdinfo->stream = cmnd->request->tag + 2;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200413 } else {
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100414 devinfo->cmnd = cmnd;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200415 cmdinfo->stream = 1;
416 }
417
418 cmnd->scsi_done = done;
419
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500420 cmdinfo->state = ALLOC_STATUS_URB | SUBMIT_STATUS_URB |
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200421 ALLOC_CMD_URB | SUBMIT_CMD_URB;
422
423 switch (cmnd->sc_data_direction) {
424 case DMA_FROM_DEVICE:
425 cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
426 break;
427 case DMA_BIDIRECTIONAL:
428 cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
429 case DMA_TO_DEVICE:
430 cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
431 case DMA_NONE:
432 break;
433 }
434
435 if (!devinfo->use_streams) {
Gerd Hoffmanndb32de12012-06-19 09:54:49 +0200436 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200437 cmdinfo->stream = 0;
438 }
439
440 err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
441 if (err) {
442 /* If we did nothing, give up now */
Matthew Wilcox92a3f762010-12-15 15:44:04 -0500443 if (cmdinfo->state & SUBMIT_STATUS_URB) {
444 usb_free_urb(cmdinfo->status_urb);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200445 return SCSI_MLQUEUE_DEVICE_BUSY;
446 }
447 spin_lock(&uas_work_lock);
448 list_add_tail(&cmdinfo->list, &uas_work_list);
449 spin_unlock(&uas_work_lock);
450 schedule_work(&uas_work);
451 }
452
453 return 0;
454}
455
Jeff Garzikf2812332010-11-16 02:10:29 -0500456static DEF_SCSI_QCMD(uas_queuecommand)
457
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200458static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
459{
460 struct scsi_device *sdev = cmnd->device;
461 sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
462 cmnd->request->tag);
463
464/* XXX: Send ABORT TASK Task Management command */
465 return FAILED;
466}
467
468static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
469{
470 struct scsi_device *sdev = cmnd->device;
471 sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
472 cmnd->request->tag);
473
474/* XXX: Send LOGICAL UNIT RESET Task Management command */
475 return FAILED;
476}
477
478static int uas_eh_target_reset_handler(struct scsi_cmnd *cmnd)
479{
480 struct scsi_device *sdev = cmnd->device;
481 sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
482 cmnd->request->tag);
483
484/* XXX: Can we reset just the one USB interface?
485 * Would calling usb_set_interface() have the right effect?
486 */
487 return FAILED;
488}
489
490static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
491{
492 struct scsi_device *sdev = cmnd->device;
493 struct uas_dev_info *devinfo = sdev->hostdata;
494 struct usb_device *udev = devinfo->udev;
495
496 sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
497 cmnd->request->tag);
498
499 if (usb_reset_device(udev))
500 return SUCCESS;
501
502 return FAILED;
503}
504
505static int uas_slave_alloc(struct scsi_device *sdev)
506{
507 sdev->hostdata = (void *)sdev->host->hostdata[0];
508 return 0;
509}
510
511static int uas_slave_configure(struct scsi_device *sdev)
512{
513 struct uas_dev_info *devinfo = sdev->hostdata;
514 scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100515 scsi_activate_tcq(sdev, devinfo->qdepth - 2);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200516 return 0;
517}
518
519static struct scsi_host_template uas_host_template = {
520 .module = THIS_MODULE,
521 .name = "uas",
522 .queuecommand = uas_queuecommand,
523 .slave_alloc = uas_slave_alloc,
524 .slave_configure = uas_slave_configure,
525 .eh_abort_handler = uas_eh_abort_handler,
526 .eh_device_reset_handler = uas_eh_device_reset_handler,
527 .eh_target_reset_handler = uas_eh_target_reset_handler,
528 .eh_bus_reset_handler = uas_eh_bus_reset_handler,
529 .can_queue = 65536, /* Is there a limit on the _host_ ? */
530 .this_id = -1,
531 .sg_tablesize = SG_NONE,
532 .cmd_per_lun = 1, /* until we override it */
533 .skip_settle_delay = 1,
534 .ordered_tag = 1,
535};
536
537static struct usb_device_id uas_usb_ids[] = {
538 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
539 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
540 /* 0xaa is a prototype device I happen to have access to */
541 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) },
542 { }
543};
544MODULE_DEVICE_TABLE(usb, uas_usb_ids);
545
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500546static int uas_is_interface(struct usb_host_interface *intf)
547{
548 return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
549 intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
550 intf->desc.bInterfaceProtocol == USB_PR_UAS);
551}
552
Sebastian Andrzej Siewiorc898add2012-01-11 12:42:32 +0100553static int uas_isnt_supported(struct usb_device *udev)
554{
555 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
556
557 dev_warn(&udev->dev, "The driver for the USB controller %s does not "
558 "support scatter-gather which is\n",
559 hcd->driver->description);
560 dev_warn(&udev->dev, "required by the UAS driver. Please try an"
561 "alternative USB controller if you wish to use UAS.\n");
562 return -ENODEV;
563}
564
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500565static int uas_switch_interface(struct usb_device *udev,
566 struct usb_interface *intf)
567{
568 int i;
Sebastian Andrzej Siewiorc898add2012-01-11 12:42:32 +0100569 int sg_supported = udev->bus->sg_tablesize != 0;
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500570
571 for (i = 0; i < intf->num_altsetting; i++) {
572 struct usb_host_interface *alt = &intf->altsetting[i];
Sebastian Andrzej Siewiorc898add2012-01-11 12:42:32 +0100573
574 if (uas_is_interface(alt)) {
575 if (!sg_supported)
576 return uas_isnt_supported(udev);
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500577 return usb_set_interface(udev,
578 alt->desc.bInterfaceNumber,
579 alt->desc.bAlternateSetting);
Sebastian Andrzej Siewiorc898add2012-01-11 12:42:32 +0100580 }
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500581 }
582
583 return -ENODEV;
584}
585
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200586static void uas_configure_endpoints(struct uas_dev_info *devinfo)
587{
588 struct usb_host_endpoint *eps[4] = { };
589 struct usb_interface *intf = devinfo->intf;
590 struct usb_device *udev = devinfo->udev;
591 struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
592 unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
593
594 devinfo->uas_sense_old = 0;
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100595 devinfo->cmnd = NULL;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200596
597 for (i = 0; i < n_endpoints; i++) {
598 unsigned char *extra = endpoint[i].extra;
599 int len = endpoint[i].extralen;
600 while (len > 1) {
601 if (extra[1] == USB_DT_PIPE_USAGE) {
602 unsigned pipe_id = extra[2];
603 if (pipe_id > 0 && pipe_id < 5)
604 eps[pipe_id - 1] = &endpoint[i];
605 break;
606 }
607 len -= extra[0];
608 extra += extra[0];
609 }
610 }
611
612 /*
613 * Assume that if we didn't find a control pipe descriptor, we're
614 * using a device with old firmware that happens to be set up like
615 * this.
616 */
617 if (!eps[0]) {
618 devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
619 devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
620 devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
621 devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);
622
623 eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
624 eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
625 eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
626 } else {
627 devinfo->cmd_pipe = usb_sndbulkpipe(udev,
628 eps[0]->desc.bEndpointAddress);
629 devinfo->status_pipe = usb_rcvbulkpipe(udev,
630 eps[1]->desc.bEndpointAddress);
631 devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
632 eps[2]->desc.bEndpointAddress);
633 devinfo->data_out_pipe = usb_sndbulkpipe(udev,
634 eps[3]->desc.bEndpointAddress);
635 }
636
637 devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
638 GFP_KERNEL);
639 if (devinfo->qdepth < 0) {
640 devinfo->qdepth = 256;
641 devinfo->use_streams = 0;
642 } else {
643 devinfo->use_streams = 1;
644 }
645}
646
Sebastian Andrzej Siewiordae51542011-12-19 17:06:08 +0100647static void uas_free_streams(struct uas_dev_info *devinfo)
648{
649 struct usb_device *udev = devinfo->udev;
650 struct usb_host_endpoint *eps[3];
651
652 eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
653 eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
654 eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
655 usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
656}
657
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200658/*
659 * XXX: What I'd like to do here is register a SCSI host for each USB host in
660 * the system. Follow usb-storage's design of registering a SCSI host for
661 * each USB device for the moment. Can implement this by walking up the
662 * USB hierarchy until we find a USB host.
663 */
664static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
665{
666 int result;
667 struct Scsi_Host *shost;
668 struct uas_dev_info *devinfo;
669 struct usb_device *udev = interface_to_usbdev(intf);
670
Matthew Wilcox89dc2902010-12-15 15:44:05 -0500671 if (uas_switch_interface(udev, intf))
672 return -ENODEV;
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200673
674 devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
675 if (!devinfo)
676 return -ENOMEM;
677
678 result = -ENOMEM;
679 shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
680 if (!shost)
681 goto free;
682
683 shost->max_cmd_len = 16 + 252;
684 shost->max_id = 1;
685 shost->sg_tablesize = udev->bus->sg_tablesize;
686
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200687 devinfo->intf = intf;
688 devinfo->udev = udev;
689 uas_configure_endpoints(devinfo);
690
Sebastian Andrzej Siewior22188f42011-12-19 20:22:39 +0100691 result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
Sebastian Andrzej Siewiordae51542011-12-19 17:06:08 +0100692 if (result)
693 goto free;
694
695 result = scsi_add_host(shost, &intf->dev);
696 if (result)
697 goto deconfig_eps;
698
699 shost->hostdata[0] = (unsigned long)devinfo;
700
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200701 scsi_scan_host(shost);
702 usb_set_intfdata(intf, shost);
703 return result;
Sebastian Andrzej Siewiordae51542011-12-19 17:06:08 +0100704
705deconfig_eps:
706 uas_free_streams(devinfo);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200707 free:
708 kfree(devinfo);
709 if (shost)
710 scsi_host_put(shost);
711 return result;
712}
713
714static int uas_pre_reset(struct usb_interface *intf)
715{
716/* XXX: Need to return 1 if it's not our device in error handling */
717 return 0;
718}
719
720static int uas_post_reset(struct usb_interface *intf)
721{
722/* XXX: Need to return 1 if it's not our device in error handling */
723 return 0;
724}
725
726static void uas_disconnect(struct usb_interface *intf)
727{
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200728 struct Scsi_Host *shost = usb_get_intfdata(intf);
729 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
730
731 scsi_remove_host(shost);
Sebastian Andrzej Siewiordae51542011-12-19 17:06:08 +0100732 uas_free_streams(devinfo);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200733 kfree(devinfo);
734}
735
736/*
737 * XXX: Should this plug into libusual so we can auto-upgrade devices from
738 * Bulk-Only to UAS?
739 */
740static struct usb_driver uas_driver = {
741 .name = "uas",
742 .probe = uas_probe,
743 .disconnect = uas_disconnect,
744 .pre_reset = uas_pre_reset,
745 .post_reset = uas_post_reset,
746 .id_table = uas_usb_ids,
747};
748
Greg Kroah-Hartman65db4302011-11-18 09:34:02 -0800749module_usb_driver(uas_driver);
Matthew Wilcox115bb1f2010-10-07 13:05:23 +0200750
751MODULE_LICENSE("GPL");
752MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");