uas.c 33.9 KB
Newer Older
Matthew Wilcox's avatar
Matthew Wilcox committed
1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * USB Attached SCSI
 * Note that this is not the same as the USB Mass Storage driver
 *
 * Copyright Matthew Wilcox for Intel Corp, 2010
 * Copyright Sarah Sharp for Intel Corp, 2010
 *
 * Distributed under the terms of the GNU GPL, version two.
 */

#include <linux/blkdev.h>
#include <linux/slab.h>
#include <linux/types.h>
14
#include <linux/module.h>
Matthew Wilcox's avatar
Matthew Wilcox committed
15
#include <linux/usb.h>
16
#include <linux/usb_usual.h>
17
#include <linux/usb/hcd.h>
Matthew Wilcox's avatar
Matthew Wilcox committed
18
#include <linux/usb/storage.h>
19
#include <linux/usb/uas.h>
Matthew Wilcox's avatar
Matthew Wilcox committed
20
21

#include <scsi/scsi.h>
22
#include <scsi/scsi_eh.h>
Matthew Wilcox's avatar
Matthew Wilcox committed
23
24
25
26
27
28
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>

29
30
#include "uas-detect.h"

Matthew Wilcox's avatar
Matthew Wilcox committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
 * The r00-r01c specs define this version of the SENSE IU data structure.
 * It's still in use by several different firmware releases.
 */
struct sense_iu_old {
	__u8 iu_id;
	__u8 rsvd1;
	__be16 tag;
	__be16 len;
	__u8 status;
	__u8 service_response;
	__u8 sense[SCSI_SENSE_BUFFERSIZE];
};

struct uas_dev_info {
	struct usb_interface *intf;
	struct usb_device *udev;
48
	struct usb_anchor cmd_urbs;
49
50
	struct usb_anchor sense_urbs;
	struct usb_anchor data_urbs;
51
	int qdepth, resetting;
52
	struct response_iu response;
Matthew Wilcox's avatar
Matthew Wilcox committed
53
54
55
	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
	unsigned use_streams:1;
	unsigned uas_sense_old:1;
56
	unsigned running_task:1;
Hans de Goede's avatar
Hans de Goede committed
57
	unsigned shutdown:1;
58
	struct scsi_cmnd *cmnd;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
59
	spinlock_t lock;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
60
	struct work_struct work;
61
	struct list_head inflight_list;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
62
	struct list_head dead_list;
Matthew Wilcox's avatar
Matthew Wilcox committed
63
64
65
};

enum {
66
	SUBMIT_STATUS_URB	= (1 << 1),
Matthew Wilcox's avatar
Matthew Wilcox committed
67
68
69
70
71
72
	ALLOC_DATA_IN_URB	= (1 << 2),
	SUBMIT_DATA_IN_URB	= (1 << 3),
	ALLOC_DATA_OUT_URB	= (1 << 4),
	SUBMIT_DATA_OUT_URB	= (1 << 5),
	ALLOC_CMD_URB		= (1 << 6),
	SUBMIT_CMD_URB		= (1 << 7),
73
74
75
76
	COMMAND_INFLIGHT        = (1 << 8),
	DATA_IN_URB_INFLIGHT    = (1 << 9),
	DATA_OUT_URB_INFLIGHT   = (1 << 10),
	COMMAND_COMPLETED       = (1 << 11),
77
	COMMAND_ABORTED         = (1 << 12),
Gerd Hoffmann's avatar
Gerd Hoffmann committed
78
	UNLINK_DATA_URBS        = (1 << 13),
Gerd Hoffmann's avatar
Gerd Hoffmann committed
79
	IS_IN_WORK_LIST         = (1 << 14),
Matthew Wilcox's avatar
Matthew Wilcox committed
80
81
82
83
84
85
86
87
88
};

/* Overrides scsi_pointer */
struct uas_cmd_info {
	unsigned int state;
	unsigned int stream;
	struct urb *cmd_urb;
	struct urb *data_in_urb;
	struct urb *data_out_urb;
89
	struct list_head list;
Matthew Wilcox's avatar
Matthew Wilcox committed
90
91
92
93
94
};

/* I hate forward declarations, but I actually have a loop */
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
				struct uas_dev_info *devinfo, gfp_t gfp);
95
static void uas_do_work(struct work_struct *work);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
96
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
97
static void uas_free_streams(struct uas_dev_info *devinfo);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
98
static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
Matthew Wilcox's avatar
Matthew Wilcox committed
99

100
/* Must be called with devinfo->lock held, will temporary unlock the lock */
101
static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
102
103
				 struct uas_cmd_info *cmdinfo,
				 unsigned long *lock_flags)
104
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
105
106
107
108
109
110
	/*
	 * The UNLINK_DATA_URBS flag makes sure uas_try_complete
	 * (called by urb completion) doesn't release cmdinfo
	 * underneath us.
	 */
	cmdinfo->state |= UNLINK_DATA_URBS;
111
	spin_unlock_irqrestore(&devinfo->lock, *lock_flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
112

113
114
115
116
	if (cmdinfo->data_in_urb)
		usb_unlink_urb(cmdinfo->data_in_urb);
	if (cmdinfo->data_out_urb)
		usb_unlink_urb(cmdinfo->data_out_urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
117

118
	spin_lock_irqsave(&devinfo->lock, *lock_flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
119
	cmdinfo->state &= ~UNLINK_DATA_URBS;
120
121
}

Matthew Wilcox's avatar
Matthew Wilcox committed
122
123
static void uas_do_work(struct work_struct *work)
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
124
125
	struct uas_dev_info *devinfo =
		container_of(work, struct uas_dev_info, work);
Matthew Wilcox's avatar
Matthew Wilcox committed
126
	struct uas_cmd_info *cmdinfo;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
127
	unsigned long flags;
128
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
129

Gerd Hoffmann's avatar
Gerd Hoffmann committed
130
	spin_lock_irqsave(&devinfo->lock, flags);
131
	list_for_each_entry(cmdinfo, &devinfo->inflight_list, list) {
Matthew Wilcox's avatar
Matthew Wilcox committed
132
		struct scsi_pointer *scp = (void *)cmdinfo;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
133
134
		struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
						      SCp);
135
136
137
138

		if (!(cmdinfo->state & IS_IN_WORK_LIST))
			continue;

139
		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
140
		if (!err)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
141
			cmdinfo->state &= ~IS_IN_WORK_LIST;
142
		else
Gerd Hoffmann's avatar
Gerd Hoffmann committed
143
			schedule_work(&devinfo->work);
Matthew Wilcox's avatar
Matthew Wilcox committed
144
	}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
145
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
146
147
}

148
static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
149
150
			      struct uas_cmd_info *cmdinfo,
			      int result, const char *caller)
151
152
153
154
155
156
157
158
159
{
	struct scsi_pointer *scp = (void *)cmdinfo;
	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);

	uas_log_cmd_state(cmnd, caller);
	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
	WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
	cmdinfo->state |= COMMAND_ABORTED;
	cmdinfo->state &= ~IS_IN_WORK_LIST;
160
	cmnd->result = result << 16;
161
	list_move_tail(&cmdinfo->list, &devinfo->dead_list);
162
163
}

164
165
static void uas_abort_inflight(struct uas_dev_info *devinfo, int result,
			       const char *caller)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
166
167
168
169
170
171
{
	struct uas_cmd_info *cmdinfo;
	struct uas_cmd_info *temp;
	unsigned long flags;

	spin_lock_irqsave(&devinfo->lock, flags);
172
	list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list, list)
173
		uas_mark_cmd_dead(devinfo, cmdinfo, result, caller);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
174
175
176
	spin_unlock_irqrestore(&devinfo->lock, flags);
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
177
178
179
180
181
182
static void uas_add_work(struct uas_cmd_info *cmdinfo)
{
	struct scsi_pointer *scp = (void *)cmdinfo;
	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
	struct uas_dev_info *devinfo = cmnd->device->hostdata;

183
	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
Gerd Hoffmann's avatar
Gerd Hoffmann committed
184
185
186
187
	cmdinfo->state |= IS_IN_WORK_LIST;
	schedule_work(&devinfo->work);
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
188
189
190
191
192
193
194
static void uas_zap_dead(struct uas_dev_info *devinfo)
{
	struct uas_cmd_info *cmdinfo;
	struct uas_cmd_info *temp;
	unsigned long flags;

	spin_lock_irqsave(&devinfo->lock, flags);
195
	list_for_each_entry_safe(cmdinfo, temp, &devinfo->dead_list, list) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
196
197
198
199
		struct scsi_pointer *scp = (void *)cmdinfo;
		struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
						      SCp);
		uas_log_cmd_state(cmnd, __func__);
200
		WARN_ON_ONCE(!(cmdinfo->state & COMMAND_ABORTED));
Gerd Hoffmann's avatar
Gerd Hoffmann committed
201
202
203
204
205
206
		/* all urbs are killed, clear inflight bits */
		cmdinfo->state &= ~(COMMAND_INFLIGHT |
				    DATA_IN_URB_INFLIGHT |
				    DATA_OUT_URB_INFLIGHT);
		uas_try_complete(cmnd, __func__);
	}
207
	devinfo->running_task = 0;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
208
209
210
	spin_unlock_irqrestore(&devinfo->lock, flags);
}

Matthew Wilcox's avatar
Matthew Wilcox committed
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
{
	struct sense_iu *sense_iu = urb->transfer_buffer;
	struct scsi_device *sdev = cmnd->device;

	if (urb->actual_length > 16) {
		unsigned len = be16_to_cpup(&sense_iu->len);
		if (len + 16 != urb->actual_length) {
			int newlen = min(len + 16, urb->actual_length) - 16;
			if (newlen < 0)
				newlen = 0;
			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
				"disagrees with IU sense data length %d, "
				"using %d bytes of sense data\n", __func__,
					urb->actual_length, len, newlen);
			len = newlen;
		}
		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
	}

	cmnd->result = sense_iu->status;
}

static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
{
	struct sense_iu_old *sense_iu = urb->transfer_buffer;
	struct scsi_device *sdev = cmnd->device;

	if (urb->actual_length > 8) {
		unsigned len = be16_to_cpup(&sense_iu->len) - 2;
		if (len + 8 != urb->actual_length) {
			int newlen = min(len + 8, urb->actual_length) - 8;
			if (newlen < 0)
				newlen = 0;
			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
				"disagrees with IU sense data length %d, "
				"using %d bytes of sense data\n", __func__,
					urb->actual_length, len, newlen);
			len = newlen;
		}
		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
	}

	cmnd->result = sense_iu->status;
255
256
257
258
259
260
261
}

static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller)
{
	struct uas_cmd_info *ci = (void *)&cmnd->SCp;

	scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:"
Gerd Hoffmann's avatar
Gerd Hoffmann committed
262
		    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
263
264
265
266
267
268
269
270
271
272
273
		    caller, cmnd, cmnd->request->tag,
		    (ci->state & SUBMIT_STATUS_URB)     ? " s-st"  : "",
		    (ci->state & ALLOC_DATA_IN_URB)     ? " a-in"  : "",
		    (ci->state & SUBMIT_DATA_IN_URB)    ? " s-in"  : "",
		    (ci->state & ALLOC_DATA_OUT_URB)    ? " a-out" : "",
		    (ci->state & SUBMIT_DATA_OUT_URB)   ? " s-out" : "",
		    (ci->state & ALLOC_CMD_URB)         ? " a-cmd" : "",
		    (ci->state & SUBMIT_CMD_URB)        ? " s-cmd" : "",
		    (ci->state & COMMAND_INFLIGHT)      ? " CMD"   : "",
		    (ci->state & DATA_IN_URB_INFLIGHT)  ? " IN"    : "",
		    (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT"   : "",
274
		    (ci->state & COMMAND_COMPLETED)     ? " done"  : "",
Gerd Hoffmann's avatar
Gerd Hoffmann committed
275
		    (ci->state & COMMAND_ABORTED)       ? " abort" : "",
Gerd Hoffmann's avatar
Gerd Hoffmann committed
276
277
		    (ci->state & UNLINK_DATA_URBS)      ? " unlink": "",
		    (ci->state & IS_IN_WORK_LIST)       ? " work"  : "");
278
279
280
281
282
}

static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
283
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
284

285
	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
286
287
	if (cmdinfo->state & (COMMAND_INFLIGHT |
			      DATA_IN_URB_INFLIGHT |
Gerd Hoffmann's avatar
Gerd Hoffmann committed
288
289
			      DATA_OUT_URB_INFLIGHT |
			      UNLINK_DATA_URBS))
290
		return -EBUSY;
291
	WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
292
293
294
	cmdinfo->state |= COMMAND_COMPLETED;
	usb_free_urb(cmdinfo->data_in_urb);
	usb_free_urb(cmdinfo->data_out_urb);
295
	if (cmdinfo->state & COMMAND_ABORTED)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
296
		scmd_printk(KERN_INFO, cmnd, "abort completed\n");
297
	list_del(&cmdinfo->list);
298
	cmnd->scsi_done(cmnd);
299
	return 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
300
301
302
}

static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
303
			  unsigned direction)
Matthew Wilcox's avatar
Matthew Wilcox committed
304
305
306
307
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
	int err;

308
	cmdinfo->state |= direction | SUBMIT_STATUS_URB;
Matthew Wilcox's avatar
Matthew Wilcox committed
309
310
	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
	if (err) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
311
		uas_add_work(cmdinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
312
313
314
315
316
317
	}
}

static void uas_stat_cmplt(struct urb *urb)
{
	struct iu *iu = urb->transfer_buffer;
318
	struct Scsi_Host *shost = urb->context;
Hans de Goede's avatar
Hans de Goede committed
319
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
Matthew Wilcox's avatar
Matthew Wilcox committed
320
	struct scsi_cmnd *cmnd;
321
	struct uas_cmd_info *cmdinfo;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
322
	unsigned long flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
323
324
325
	u16 tag;

	if (urb->status) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
326
327
328
329
330
331
332
		if (urb->status == -ENOENT) {
			dev_err(&urb->dev->dev, "stat urb: killed, stream %d\n",
				urb->stream_id);
		} else {
			dev_err(&urb->dev->dev, "stat urb: status %d\n",
				urb->status);
		}
333
		usb_free_urb(urb);
Matthew Wilcox's avatar
Matthew Wilcox committed
334
335
336
		return;
	}

337
338
339
340
341
	if (devinfo->resetting) {
		usb_free_urb(urb);
		return;
	}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
342
	spin_lock_irqsave(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
343
	tag = be16_to_cpup(&iu->tag) - 1;
344
345
	if (tag == 0)
		cmnd = devinfo->cmnd;
Matthew Wilcox's avatar
Matthew Wilcox committed
346
	else
347
		cmnd = scsi_host_find_tag(shost, tag - 1);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
348

349
	if (!cmnd) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
350
		if (iu->iu_id == IU_ID_RESPONSE) {
351
352
353
			if (!devinfo->running_task)
				dev_warn(&urb->dev->dev,
				    "stat urb: recv unexpected response iu\n");
Gerd Hoffmann's avatar
Gerd Hoffmann committed
354
355
			/* store results for uas_eh_task_mgmt() */
			memcpy(&devinfo->response, iu, sizeof(devinfo->response));
356
		}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
357
358
359
		usb_free_urb(urb);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return;
360
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
361

Gerd Hoffmann's avatar
Gerd Hoffmann committed
362
	cmdinfo = (void *)&cmnd->SCp;
Matthew Wilcox's avatar
Matthew Wilcox committed
363
364
	switch (iu->iu_id) {
	case IU_ID_STATUS:
365
366
367
		if (devinfo->cmnd == cmnd)
			devinfo->cmnd = NULL;

Matthew Wilcox's avatar
Matthew Wilcox committed
368
369
370
371
372
373
		if (urb->actual_length < 16)
			devinfo->uas_sense_old = 1;
		if (devinfo->uas_sense_old)
			uas_sense_old(urb, cmnd);
		else
			uas_sense(urb, cmnd);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
374
375
		if (cmnd->result != 0) {
			/* cancel data transfers on error */
376
			uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
377
		}
378
379
		cmdinfo->state &= ~COMMAND_INFLIGHT;
		uas_try_complete(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
380
381
		break;
	case IU_ID_READ_READY:
382
383
384
385
386
		if (!cmdinfo->data_in_urb ||
				(cmdinfo->state & DATA_IN_URB_INFLIGHT)) {
			scmd_printk(KERN_ERR, cmnd, "unexpected read rdy\n");
			break;
		}
Matthew Wilcox's avatar
Matthew Wilcox committed
387
388
389
		uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
		break;
	case IU_ID_WRITE_READY:
390
391
392
393
394
		if (!cmdinfo->data_out_urb ||
				(cmdinfo->state & DATA_OUT_URB_INFLIGHT)) {
			scmd_printk(KERN_ERR, cmnd, "unexpected write rdy\n");
			break;
		}
Matthew Wilcox's avatar
Matthew Wilcox committed
395
396
397
398
399
400
		uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
		break;
	default:
		scmd_printk(KERN_ERR, cmnd,
			"Bogus IU (%d) received on status pipe\n", iu->iu_id);
	}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
401
	usb_free_urb(urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
402
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
403
404
}

405
static void uas_data_cmplt(struct urb *urb)
Matthew Wilcox's avatar
Matthew Wilcox committed
406
{
407
408
	struct scsi_cmnd *cmnd = urb->context;
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
409
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
410
	struct scsi_data_buffer *sdb = NULL;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
411
	unsigned long flags;
412

Gerd Hoffmann's avatar
Gerd Hoffmann committed
413
	spin_lock_irqsave(&devinfo->lock, flags);
414
415
416
417
418
419
420
	if (cmdinfo->data_in_urb == urb) {
		sdb = scsi_in(cmnd);
		cmdinfo->state &= ~DATA_IN_URB_INFLIGHT;
	} else if (cmdinfo->data_out_urb == urb) {
		sdb = scsi_out(cmnd);
		cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT;
	}
421
422
423
	if (sdb == NULL) {
		WARN_ON_ONCE(1);
	} else if (urb->status) {
Hans de Goede's avatar
Hans de Goede committed
424
425
426
427
428
429
		if (urb->status != -ECONNRESET) {
			uas_log_cmd_state(cmnd, __func__);
			scmd_printk(KERN_ERR, cmnd,
				"data cmplt err %d stream %d\n",
				urb->status, urb->stream_id);
		}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
430
431
432
433
434
		/* error: no data transfered */
		sdb->resid = sdb->length;
	} else {
		sdb->resid = sdb->length - urb->actual_length;
	}
435
	uas_try_complete(cmnd, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
436
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
437
438
}

Hans de Goede's avatar
Hans de Goede committed
439
440
441
442
443
444
445
446
447
448
449
static void uas_cmd_cmplt(struct urb *urb)
{
	struct scsi_cmnd *cmnd = urb->context;

	if (urb->status) {
		uas_log_cmd_state(cmnd, __func__);
		scmd_printk(KERN_ERR, cmnd, "cmd cmplt err %d\n", urb->status);
	}
	usb_free_urb(urb);
}

Matthew Wilcox's avatar
Matthew Wilcox committed
450
static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
451
452
453
				      unsigned int pipe, u16 stream_id,
				      struct scsi_cmnd *cmnd,
				      enum dma_data_direction dir)
Matthew Wilcox's avatar
Matthew Wilcox committed
454
455
456
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
457
458
	struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
		? scsi_in(cmnd) : scsi_out(cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
459
460
461

	if (!urb)
		goto out;
462
463
	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
			  uas_data_cmplt, cmnd);
464
	urb->stream_id = stream_id;
Matthew Wilcox's avatar
Matthew Wilcox committed
465
466
467
468
469
470
471
	urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
	urb->sg = sdb->table.sgl;
 out:
	return urb;
}

static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
Gerd Hoffmann's avatar
Gerd Hoffmann committed
472
				       struct Scsi_Host *shost, u16 stream_id)
Matthew Wilcox's avatar
Matthew Wilcox committed
473
474
475
476
477
478
479
480
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct sense_iu *iu;

	if (!urb)
		goto out;

481
	iu = kzalloc(sizeof(*iu), gfp);
Matthew Wilcox's avatar
Matthew Wilcox committed
482
483
484
485
	if (!iu)
		goto free;

	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
Gerd Hoffmann's avatar
Gerd Hoffmann committed
486
						uas_stat_cmplt, shost);
Matthew Wilcox's avatar
Matthew Wilcox committed
487
488
489
490
491
492
493
494
495
496
	urb->stream_id = stream_id;
	urb->transfer_flags |= URB_FREE_BUFFER;
 out:
	return urb;
 free:
	usb_free_urb(urb);
	return NULL;
}

static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
497
					struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
{
	struct usb_device *udev = devinfo->udev;
	struct scsi_device *sdev = cmnd->device;
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct command_iu *iu;
	int len;

	if (!urb)
		goto out;

	len = cmnd->cmd_len - 16;
	if (len < 0)
		len = 0;
	len = ALIGN(len, 4);
512
	iu = kzalloc(sizeof(*iu) + len, gfp);
Matthew Wilcox's avatar
Matthew Wilcox committed
513
514
515
516
	if (!iu)
		goto free;

	iu->iu_id = IU_ID_COMMAND;
517
	if (blk_rq_tagged(cmnd->request))
518
		iu->tag = cpu_to_be16(cmnd->request->tag + 2);
519
520
	else
		iu->tag = cpu_to_be16(1);
521
	iu->prio_attr = UAS_SIMPLE_TAG;
Matthew Wilcox's avatar
Matthew Wilcox committed
522
523
524
525
526
	iu->len = len;
	int_to_scsilun(sdev->lun, &iu->lun);
	memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);

	usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
Hans de Goede's avatar
Hans de Goede committed
527
							uas_cmd_cmplt, cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
528
529
530
531
532
533
534
535
	urb->transfer_flags |= URB_FREE_BUFFER;
 out:
	return urb;
 free:
	usb_free_urb(urb);
	return NULL;
}

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
static int uas_submit_task_urb(struct scsi_cmnd *cmnd, gfp_t gfp,
			       u8 function, u16 stream_id)
{
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct task_mgmt_iu *iu;
	int err = -ENOMEM;

	if (!urb)
		goto err;

	iu = kzalloc(sizeof(*iu), gfp);
	if (!iu)
		goto err;

	iu->iu_id = IU_ID_TASK_MGMT;
	iu->tag = cpu_to_be16(stream_id);
	int_to_scsilun(cmnd->device->lun, &iu->lun);

	iu->function = function;
	switch (function) {
	case TMF_ABORT_TASK:
		if (blk_rq_tagged(cmnd->request))
			iu->task_tag = cpu_to_be16(cmnd->request->tag + 2);
		else
			iu->task_tag = cpu_to_be16(1);
		break;
	}

	usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu),
Hans de Goede's avatar
Hans de Goede committed
567
			  uas_cmd_cmplt, cmnd);
568
569
	urb->transfer_flags |= URB_FREE_BUFFER;

570
	usb_anchor_urb(urb, &devinfo->cmd_urbs);
571
	err = usb_submit_urb(urb, gfp);
572
573
	if (err) {
		usb_unanchor_urb(urb);
Hans de Goede's avatar
Hans de Goede committed
574
575
		uas_log_cmd_state(cmnd, __func__);
		scmd_printk(KERN_ERR, cmnd, "task submission err %d\n", err);
576
		goto err;
577
	}
578
579
580
581
582
583
584
585

	return 0;

err:
	usb_free_urb(urb);
	return err;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
586
587
588
589
590
591
/*
 * Why should I request the Status IU before sending the Command IU?  Spec
 * says to, but also says the device may receive them in any order.  Seems
 * daft to me.
 */

Hans de Goede's avatar
Hans de Goede committed
592
static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd,
593
					gfp_t gfp, unsigned int stream)
Matthew Wilcox's avatar
Matthew Wilcox committed
594
{
Hans de Goede's avatar
Hans de Goede committed
595
	struct Scsi_Host *shost = cmnd->device->host;
Hans de Goede's avatar
Hans de Goede committed
596
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
597
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
598
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
599

Gerd Hoffmann's avatar
Gerd Hoffmann committed
600
601
	urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
	if (!urb)
602
		return NULL;
603
	usb_anchor_urb(urb, &devinfo->sense_urbs);
Hans de Goede's avatar
Hans de Goede committed
604
605
	err = usb_submit_urb(urb, gfp);
	if (err) {
606
		usb_unanchor_urb(urb);
Hans de Goede's avatar
Hans de Goede committed
607
		uas_log_cmd_state(cmnd, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
608
		shost_printk(KERN_INFO, shost,
Hans de Goede's avatar
Hans de Goede committed
609
610
			     "sense urb submission error %d stream %d\n",
			     err, stream);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
611
		usb_free_urb(urb);
612
		return NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
613
	}
614
	return urb;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
615
616
617
618
619
620
}

static int uas_submit_urbs(struct scsi_cmnd *cmnd,
			   struct uas_dev_info *devinfo, gfp_t gfp)
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
621
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
622
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
623

624
	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
625
	if (cmdinfo->state & SUBMIT_STATUS_URB) {
Hans de Goede's avatar
Hans de Goede committed
626
		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
627
628
		if (!urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
629
		cmdinfo->state &= ~SUBMIT_STATUS_URB;
Matthew Wilcox's avatar
Matthew Wilcox committed
630
631
632
633
	}

	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
634
					devinfo->data_in_pipe, cmdinfo->stream,
635
					cmnd, DMA_FROM_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
636
637
638
639
640
641
		if (!cmdinfo->data_in_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
642
		usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
Hans de Goede's avatar
Hans de Goede committed
643
644
		err = usb_submit_urb(cmdinfo->data_in_urb, gfp);
		if (err) {
645
			usb_unanchor_urb(cmdinfo->data_in_urb);
Hans de Goede's avatar
Hans de Goede committed
646
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
647
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
648
649
				"data in urb submission error %d stream %d\n",
				err, cmdinfo->data_in_urb->stream_id);
Matthew Wilcox's avatar
Matthew Wilcox committed
650
651
652
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
653
		cmdinfo->state |= DATA_IN_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
654
655
656
657
	}

	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
658
					devinfo->data_out_pipe, cmdinfo->stream,
659
					cmnd, DMA_TO_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
660
661
662
663
664
665
		if (!cmdinfo->data_out_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
666
		usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
Hans de Goede's avatar
Hans de Goede committed
667
668
		err = usb_submit_urb(cmdinfo->data_out_urb, gfp);
		if (err) {
669
			usb_unanchor_urb(cmdinfo->data_out_urb);
Hans de Goede's avatar
Hans de Goede committed
670
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
671
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
672
673
				"data out urb submission error %d stream %d\n",
				err, cmdinfo->data_out_urb->stream_id);
Matthew Wilcox's avatar
Matthew Wilcox committed
674
675
676
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
677
		cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
678
679
680
	}

	if (cmdinfo->state & ALLOC_CMD_URB) {
681
		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
682
683
684
685
686
687
		if (!cmdinfo->cmd_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_CMD_URB;
	}

	if (cmdinfo->state & SUBMIT_CMD_URB) {
688
		usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
Hans de Goede's avatar
Hans de Goede committed
689
690
		err = usb_submit_urb(cmdinfo->cmd_urb, gfp);
		if (err) {
691
			usb_unanchor_urb(cmdinfo->cmd_urb);
Hans de Goede's avatar
Hans de Goede committed
692
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
693
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
694
				    "cmd urb submission error %d\n", err);
Matthew Wilcox's avatar
Matthew Wilcox committed
695
696
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
697
		cmdinfo->cmd_urb = NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
698
		cmdinfo->state &= ~SUBMIT_CMD_URB;
699
		cmdinfo->state |= COMMAND_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
700
701
702
703
704
	}

	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
705
static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
Matthew Wilcox's avatar
Matthew Wilcox committed
706
707
708
709
710
					void (*done)(struct scsi_cmnd *))
{
	struct scsi_device *sdev = cmnd->device;
	struct uas_dev_info *devinfo = sdev->hostdata;
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
711
	unsigned long flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
712
713
714
715
	int err;

	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));

716
717
	spin_lock_irqsave(&devinfo->lock, flags);

718
719
720
	if (devinfo->resetting) {
		cmnd->result = DID_ERROR << 16;
		cmnd->scsi_done(cmnd);
721
		spin_unlock_irqrestore(&devinfo->lock, flags);
722
723
724
		return 0;
	}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
725
726
	if (devinfo->cmnd) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
727
		return SCSI_MLQUEUE_DEVICE_BUSY;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
728
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
729

730
731
	memset(cmdinfo, 0, sizeof(*cmdinfo));

Matthew Wilcox's avatar
Matthew Wilcox committed
732
	if (blk_rq_tagged(cmnd->request)) {
733
		cmdinfo->stream = cmnd->request->tag + 2;
Matthew Wilcox's avatar
Matthew Wilcox committed
734
	} else {
735
		devinfo->cmnd = cmnd;
Matthew Wilcox's avatar
Matthew Wilcox committed
736
737
738
739
740
		cmdinfo->stream = 1;
	}

	cmnd->scsi_done = done;

Gerd Hoffmann's avatar
Gerd Hoffmann committed
741
	cmdinfo->state = SUBMIT_STATUS_URB |
Matthew Wilcox's avatar
Matthew Wilcox committed
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
			ALLOC_CMD_URB | SUBMIT_CMD_URB;

	switch (cmnd->sc_data_direction) {
	case DMA_FROM_DEVICE:
		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
		break;
	case DMA_BIDIRECTIONAL:
		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
	case DMA_TO_DEVICE:
		cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
	case DMA_NONE:
		break;
	}

	if (!devinfo->use_streams) {
757
		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
Matthew Wilcox's avatar
Matthew Wilcox committed
758
759
760
761
762
763
		cmdinfo->stream = 0;
	}

	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
	if (err) {
		/* If we did nothing, give up now */
764
		if (cmdinfo->state & SUBMIT_STATUS_URB) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
765
			spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
766
767
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
768
		uas_add_work(cmdinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
769
770
	}

771
	list_add_tail(&cmdinfo->list, &devinfo->inflight_list);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
772
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
773
774
775
	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
776
777
static DEF_SCSI_QCMD(uas_queuecommand)

778
779
static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
			    const char *fname, u8 function)
Matthew Wilcox's avatar
Matthew Wilcox committed
780
{
781
	struct Scsi_Host *shost = cmnd->device->host;
Hans de Goede's avatar
Hans de Goede committed
782
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
783
	u16 tag = devinfo->qdepth;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
784
	unsigned long flags;
785
	struct urb *sense_urb;
786
	int result = SUCCESS;
Matthew Wilcox's avatar
Matthew Wilcox committed
787

Gerd Hoffmann's avatar
Gerd Hoffmann committed
788
	spin_lock_irqsave(&devinfo->lock, flags);
789

790
791
792
793
794
	if (devinfo->resetting) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return FAILED;
	}

795
796
797
798
799
800
801
802
803
	if (devinfo->running_task) {
		shost_printk(KERN_INFO, shost,
			     "%s: %s: error already running a task\n",
			     __func__, fname);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return FAILED;
	}

	devinfo->running_task = 1;
804
	memset(&devinfo->response, 0, sizeof(devinfo->response));
Hans de Goede's avatar
Hans de Goede committed
805
	sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO,
806
					 devinfo->use_streams ? tag : 0);
807
	if (!sense_urb) {
808
809
810
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit sense urb failed\n",
			     __func__, fname);
811
		devinfo->running_task = 0;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
812
		spin_unlock_irqrestore(&devinfo->lock, flags);
813
814
		return FAILED;
	}
815
	if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) {
816
817
818
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit task mgmt urb failed\n",
			     __func__, fname);
819
		devinfo->running_task = 0;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
820
		spin_unlock_irqrestore(&devinfo->lock, flags);
821
		usb_kill_urb(sense_urb);
822
823
		return FAILED;
	}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
824
825
826
	spin_unlock_irqrestore(&devinfo->lock, flags);

	if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
827
828
829
830
831
832
		/*
		 * Note we deliberately do not clear running_task here. If we
		 * allow new tasks to be submitted, there is no way to figure
		 * out if a received response_iu is for the failed task or for
		 * the new one. A bus-reset will eventually clear running_task.
		 */
833
834
835
836
		shost_printk(KERN_INFO, shost,
			     "%s: %s timed out\n", __func__, fname);
		return FAILED;
	}
837
838
839

	spin_lock_irqsave(&devinfo->lock, flags);
	devinfo->running_task = 0;
840
841
842
843
	if (be16_to_cpu(devinfo->response.tag) != tag) {
		shost_printk(KERN_INFO, shost,
			     "%s: %s failed (wrong tag %d/%d)\n", __func__,
			     fname, be16_to_cpu(devinfo->response.tag), tag);
844
845
		result = FAILED;
	} else if (devinfo->response.response_code != RC_TMF_COMPLETE) {
846
847
848
		shost_printk(KERN_INFO, shost,
			     "%s: %s failed (rc 0x%x)\n", __func__,
			     fname, devinfo->response.response_code);
849
		result = FAILED;
850
	}
851
852
853
	spin_unlock_irqrestore(&devinfo->lock, flags);

	return result;
Matthew Wilcox's avatar
Matthew Wilcox committed
854
855
}

856
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
857
{
858
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
859
860
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
	unsigned long flags;
861
	int ret;
Matthew Wilcox's avatar
Matthew Wilcox committed
862

Gerd Hoffmann's avatar
Gerd Hoffmann committed
863
	spin_lock_irqsave(&devinfo->lock, flags);
864
865
866
867
868
869

	if (devinfo->resetting) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return FAILED;
	}

870
	uas_mark_cmd_dead(devinfo, cmdinfo, DID_ABORT, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
871
872
873
874
	if (cmdinfo->state & COMMAND_INFLIGHT) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
	} else {
875
		uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
876
877
878
879
		uas_try_complete(cmnd, __func__);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = SUCCESS;
	}
880
	return ret;
Matthew Wilcox's avatar
Matthew Wilcox committed
881
882
}

883
static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
884
{
885
886
887
	sdev_printk(KERN_INFO, cmnd->device, "%s\n", __func__);
	return uas_eh_task_mgmt(cmnd, "LOGICAL UNIT RESET",
				TMF_LOGICAL_UNIT_RESET);
Matthew Wilcox's avatar
Matthew Wilcox committed
888
889
890
891
892
893
894
}

static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
{
	struct scsi_device *sdev = cmnd->device;
	struct uas_dev_info *devinfo = sdev->hostdata;
	struct usb_device *udev = devinfo->udev;
895
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
896

Hans de Goede's avatar
Hans de Goede committed
897
898
899
900
901
902
903
	err = usb_lock_device_for_reset(udev, devinfo->intf);
	if (err) {
		shost_printk(KERN_ERR, sdev->host,
			     "%s FAILED to get lock err %d\n", __func__, err);
		return FAILED;
	}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
904
	shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
905
	devinfo->resetting = 1;
906
	uas_abort_inflight(devinfo, DID_RESET, __func__);
907
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
908
909
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
910
	uas_zap_dead(devinfo);
911
912
	err = usb_reset_device(udev);
	devinfo->resetting = 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
913

Hans de Goede's avatar
Hans de Goede committed
914
915
	usb_unlock_device(udev);

916
917
918
919
	if (err) {
		shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
		return FAILED;
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
920

921
922
	shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__);
	return SUCCESS;
Matthew Wilcox's avatar
Matthew Wilcox committed
923
924
925
926
}

static int uas_slave_alloc(struct scsi_device *sdev)
{
Hans de Goede's avatar
Hans de Goede committed
927
	sdev->hostdata = (void *)sdev->host->hostdata;
Matthew Wilcox's avatar
Matthew Wilcox committed
928
929
930
931
932
933
934
	return 0;
}

static int uas_slave_configure(struct scsi_device *sdev)
{
	struct uas_dev_info *devinfo = sdev->hostdata;
	scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
935
	scsi_activate_tcq(sdev, devinfo->qdepth - 2);
Matthew Wilcox's avatar
Matthew Wilcox committed
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
	return 0;
}

static struct scsi_host_template uas_host_template = {
	.module = THIS_MODULE,
	.name = "uas",
	.queuecommand = uas_queuecommand,
	.slave_alloc = uas_slave_alloc,
	.slave_configure = uas_slave_configure,
	.eh_abort_handler = uas_eh_abort_handler,
	.eh_device_reset_handler = uas_eh_device_reset_handler,
	.eh_bus_reset_handler = uas_eh_bus_reset_handler,
	.can_queue = 65536,	/* Is there a limit on the _host_ ? */
	.this_id = -1,
	.sg_tablesize = SG_NONE,
	.cmd_per_lun = 1,	/* until we override it */
	.skip_settle_delay = 1,
	.ordered_tag = 1,
};

956
957
958
959
960
961
#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
		    vendorName, productName, useProtocol, useTransport, \
		    initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
	.driver_info = (flags) }

Matthew Wilcox's avatar
Matthew Wilcox committed
962
static struct usb_device_id uas_usb_ids[] = {
963
#	include "unusual_uas.h"
Matthew Wilcox's avatar
Matthew Wilcox committed
964
965
966
967
968
969
970
971
	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
	/* 0xaa is a prototype device I happen to have access to */
	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) },
	{ }
};
MODULE_DEVICE_TABLE(usb, uas_usb_ids);

972
973
#undef UNUSUAL_DEV

974
975
976
977
978
979
980
981
982
983
984
985
986
static int uas_switch_interface(struct usb_device *udev,
				struct usb_interface *intf)
{
	int alt;

	alt = uas_find_uas_alt_setting(intf);
	if (alt < 0)
		return alt;

	return usb_set_interface(udev,
			intf->altsetting[0].desc.bInterfaceNumber, alt);
}