uas.c 33.6 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
382
383
384
385
386
387
388
389
390
		break;
	case IU_ID_READ_READY:
		uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
		break;
	case IU_ID_WRITE_READY:
		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
391
	usb_free_urb(urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
392
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
393
394
}

395
static void uas_data_cmplt(struct urb *urb)
Matthew Wilcox's avatar
Matthew Wilcox committed
396
{
397
398
	struct scsi_cmnd *cmnd = urb->context;
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
399
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
400
	struct scsi_data_buffer *sdb = NULL;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
401
	unsigned long flags;
402

Gerd Hoffmann's avatar
Gerd Hoffmann committed
403
	spin_lock_irqsave(&devinfo->lock, flags);
404
405
406
407
408
409
410
	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;
	}
411
412
413
	if (sdb == NULL) {
		WARN_ON_ONCE(1);
	} else if (urb->status) {
Hans de Goede's avatar
Hans de Goede committed
414
415
416
417
418
419
		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
420
421
422
423
424
		/* error: no data transfered */
		sdb->resid = sdb->length;
	} else {
		sdb->resid = sdb->length - urb->actual_length;
	}
425
	uas_try_complete(cmnd, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
426
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
427
428
}

Hans de Goede's avatar
Hans de Goede committed
429
430
431
432
433
434
435
436
437
438
439
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
440
static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
441
442
443
				      unsigned int pipe, u16 stream_id,
				      struct scsi_cmnd *cmnd,
				      enum dma_data_direction dir)
Matthew Wilcox's avatar
Matthew Wilcox committed
444
445
446
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
447
448
	struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
		? scsi_in(cmnd) : scsi_out(cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
449
450
451

	if (!urb)
		goto out;
452
453
	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
			  uas_data_cmplt, cmnd);
454
	urb->stream_id = stream_id;
Matthew Wilcox's avatar
Matthew Wilcox committed
455
456
457
458
459
460
461
	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
462
				       struct Scsi_Host *shost, u16 stream_id)
Matthew Wilcox's avatar
Matthew Wilcox committed
463
464
465
466
467
468
469
470
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct sense_iu *iu;

	if (!urb)
		goto out;

471
	iu = kzalloc(sizeof(*iu), gfp);
Matthew Wilcox's avatar
Matthew Wilcox committed
472
473
474
475
	if (!iu)
		goto free;

	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
Gerd Hoffmann's avatar
Gerd Hoffmann committed
476
						uas_stat_cmplt, shost);
Matthew Wilcox's avatar
Matthew Wilcox committed
477
478
479
480
481
482
483
484
485
486
	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,
487
					struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
{
	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);
502
	iu = kzalloc(sizeof(*iu) + len, gfp);
Matthew Wilcox's avatar
Matthew Wilcox committed
503
504
505
506
	if (!iu)
		goto free;

	iu->iu_id = IU_ID_COMMAND;
507
	if (blk_rq_tagged(cmnd->request))
508
		iu->tag = cpu_to_be16(cmnd->request->tag + 2);
509
510
	else
		iu->tag = cpu_to_be16(1);
511
	iu->prio_attr = UAS_SIMPLE_TAG;
Matthew Wilcox's avatar
Matthew Wilcox committed
512
513
514
515
516
	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
517
							uas_cmd_cmplt, cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
518
519
520
521
522
523
524
525
	urb->transfer_flags |= URB_FREE_BUFFER;
 out:
	return urb;
 free:
	usb_free_urb(urb);
	return NULL;
}

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
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
557
			  uas_cmd_cmplt, cmnd);
558
559
	urb->transfer_flags |= URB_FREE_BUFFER;

560
	usb_anchor_urb(urb, &devinfo->cmd_urbs);
561
	err = usb_submit_urb(urb, gfp);
562
563
	if (err) {
		usb_unanchor_urb(urb);
Hans de Goede's avatar
Hans de Goede committed
564
565
		uas_log_cmd_state(cmnd, __func__);
		scmd_printk(KERN_ERR, cmnd, "task submission err %d\n", err);
566
		goto err;
567
	}
568
569
570
571
572
573
574
575

	return 0;

err:
	usb_free_urb(urb);
	return err;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
576
577
578
579
580
581
/*
 * 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
582
static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd,
583
					gfp_t gfp, unsigned int stream)
Matthew Wilcox's avatar
Matthew Wilcox committed
584
{
Hans de Goede's avatar
Hans de Goede committed
585
	struct Scsi_Host *shost = cmnd->device->host;
Hans de Goede's avatar
Hans de Goede committed
586
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
587
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
588
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
589

Gerd Hoffmann's avatar
Gerd Hoffmann committed
590
591
	urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
	if (!urb)
592
		return NULL;
593
	usb_anchor_urb(urb, &devinfo->sense_urbs);
Hans de Goede's avatar
Hans de Goede committed
594
595
	err = usb_submit_urb(urb, gfp);
	if (err) {
596
		usb_unanchor_urb(urb);
Hans de Goede's avatar
Hans de Goede committed
597
		uas_log_cmd_state(cmnd, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
598
		shost_printk(KERN_INFO, shost,
Hans de Goede's avatar
Hans de Goede committed
599
600
			     "sense urb submission error %d stream %d\n",
			     err, stream);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
601
		usb_free_urb(urb);
602
		return NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
603
	}
604
	return urb;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
605
606
607
608
609
610
}

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;
611
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
612
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
613

614
	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
615
	if (cmdinfo->state & SUBMIT_STATUS_URB) {
Hans de Goede's avatar
Hans de Goede committed
616
		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
617
618
		if (!urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
619
		cmdinfo->state &= ~SUBMIT_STATUS_URB;
Matthew Wilcox's avatar
Matthew Wilcox committed
620
621
622
623
	}

	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
624
					devinfo->data_in_pipe, cmdinfo->stream,
625
					cmnd, DMA_FROM_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
626
627
628
629
630
631
		if (!cmdinfo->data_in_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
632
		usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
Hans de Goede's avatar
Hans de Goede committed
633
634
		err = usb_submit_urb(cmdinfo->data_in_urb, gfp);
		if (err) {
635
			usb_unanchor_urb(cmdinfo->data_in_urb);
Hans de Goede's avatar
Hans de Goede committed
636
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
637
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
638
639
				"data in urb submission error %d stream %d\n",
				err, cmdinfo->data_in_urb->stream_id);
Matthew Wilcox's avatar
Matthew Wilcox committed
640
641
642
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
643
		cmdinfo->state |= DATA_IN_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
644
645
646
647
	}

	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
648
					devinfo->data_out_pipe, cmdinfo->stream,
649
					cmnd, DMA_TO_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
650
651
652
653
654
655
		if (!cmdinfo->data_out_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
656
		usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
Hans de Goede's avatar
Hans de Goede committed
657
658
		err = usb_submit_urb(cmdinfo->data_out_urb, gfp);
		if (err) {
659
			usb_unanchor_urb(cmdinfo->data_out_urb);
Hans de Goede's avatar
Hans de Goede committed
660
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
661
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
662
663
				"data out urb submission error %d stream %d\n",
				err, cmdinfo->data_out_urb->stream_id);
Matthew Wilcox's avatar
Matthew Wilcox committed
664
665
666
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
667
		cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
668
669
670
	}

	if (cmdinfo->state & ALLOC_CMD_URB) {
671
		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
672
673
674
675
676
677
		if (!cmdinfo->cmd_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_CMD_URB;
	}

	if (cmdinfo->state & SUBMIT_CMD_URB) {
678
		usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
Hans de Goede's avatar
Hans de Goede committed
679
680
		err = usb_submit_urb(cmdinfo->cmd_urb, gfp);
		if (err) {
681
			usb_unanchor_urb(cmdinfo->cmd_urb);
Hans de Goede's avatar
Hans de Goede committed
682
			uas_log_cmd_state(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
683
			scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
684
				    "cmd urb submission error %d\n", err);
Matthew Wilcox's avatar
Matthew Wilcox committed
685
686
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
687
		cmdinfo->cmd_urb = NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
688
		cmdinfo->state &= ~SUBMIT_CMD_URB;
689
		cmdinfo->state |= COMMAND_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
690
691
692
693
694
	}

	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
695
static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
Matthew Wilcox's avatar
Matthew Wilcox committed
696
697
698
699
700
					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
701
	unsigned long flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
702
703
704
705
	int err;

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

706
707
	spin_lock_irqsave(&devinfo->lock, flags);

708
709
710
	if (devinfo->resetting) {
		cmnd->result = DID_ERROR << 16;
		cmnd->scsi_done(cmnd);
711
		spin_unlock_irqrestore(&devinfo->lock, flags);
712
713
714
		return 0;
	}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
715
716
	if (devinfo->cmnd) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
717
		return SCSI_MLQUEUE_DEVICE_BUSY;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
718
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
719

720
721
	memset(cmdinfo, 0, sizeof(*cmdinfo));

Matthew Wilcox's avatar
Matthew Wilcox committed
722
	if (blk_rq_tagged(cmnd->request)) {
723
		cmdinfo->stream = cmnd->request->tag + 2;
Matthew Wilcox's avatar
Matthew Wilcox committed
724
	} else {
725
		devinfo->cmnd = cmnd;
Matthew Wilcox's avatar
Matthew Wilcox committed
726
727
728
729
730
		cmdinfo->stream = 1;
	}

	cmnd->scsi_done = done;

Gerd Hoffmann's avatar
Gerd Hoffmann committed
731
	cmdinfo->state = SUBMIT_STATUS_URB |
Matthew Wilcox's avatar
Matthew Wilcox committed
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
			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) {
747
		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
Matthew Wilcox's avatar
Matthew Wilcox committed
748
749
750
751
752
753
		cmdinfo->stream = 0;
	}

	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
	if (err) {
		/* If we did nothing, give up now */
754
		if (cmdinfo->state & SUBMIT_STATUS_URB) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
755
			spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
756
757
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
758
		uas_add_work(cmdinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
759
760
	}

761
	list_add_tail(&cmdinfo->list, &devinfo->inflight_list);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
762
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
763
764
765
	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
766
767
static DEF_SCSI_QCMD(uas_queuecommand)

768
769
static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
			    const char *fname, u8 function)
Matthew Wilcox's avatar
Matthew Wilcox committed
770
{
771
	struct Scsi_Host *shost = cmnd->device->host;
Hans de Goede's avatar
Hans de Goede committed
772
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
773
	u16 tag = devinfo->qdepth;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
774
	unsigned long flags;
775
	struct urb *sense_urb;
776
	int result = SUCCESS;
Matthew Wilcox's avatar
Matthew Wilcox committed
777

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

780
781
782
783
784
	if (devinfo->resetting) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return FAILED;
	}

785
786
787
788
789
790
791
792
793
	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;
794
	memset(&devinfo->response, 0, sizeof(devinfo->response));
Hans de Goede's avatar
Hans de Goede committed
795
	sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO,
796
					 devinfo->use_streams ? tag : 0);
797
	if (!sense_urb) {
798
799
800
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit sense urb failed\n",
			     __func__, fname);
801
		devinfo->running_task = 0;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
802
		spin_unlock_irqrestore(&devinfo->lock, flags);
803
804
		return FAILED;
	}
805
	if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) {
806
807
808
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit task mgmt urb failed\n",
			     __func__, fname);
809
		devinfo->running_task = 0;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
810
		spin_unlock_irqrestore(&devinfo->lock, flags);
811
		usb_kill_urb(sense_urb);
812
813
		return FAILED;
	}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
814
815
816
	spin_unlock_irqrestore(&devinfo->lock, flags);

	if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
817
818
819
820
821
822
		/*
		 * 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.
		 */
823
824
825
826
		shost_printk(KERN_INFO, shost,
			     "%s: %s timed out\n", __func__, fname);
		return FAILED;
	}
827
828
829

	spin_lock_irqsave(&devinfo->lock, flags);
	devinfo->running_task = 0;
830
831
832
833
	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);
834
835
		result = FAILED;
	} else if (devinfo->response.response_code != RC_TMF_COMPLETE) {
836
837
838
		shost_printk(KERN_INFO, shost,
			     "%s: %s failed (rc 0x%x)\n", __func__,
			     fname, devinfo->response.response_code);
839
		result = FAILED;
840
	}
841
842
843
	spin_unlock_irqrestore(&devinfo->lock, flags);

	return result;
Matthew Wilcox's avatar
Matthew Wilcox committed
844
845
}

846
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
847
{
848
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
849
850
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
	unsigned long flags;
851
	int ret;
Matthew Wilcox's avatar
Matthew Wilcox committed
852

Gerd Hoffmann's avatar
Gerd Hoffmann committed
853
	spin_lock_irqsave(&devinfo->lock, flags);
854
855
856
857
858
859

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

860
	uas_mark_cmd_dead(devinfo, cmdinfo, DID_ABORT, __func__);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
861
862
863
864
	if (cmdinfo->state & COMMAND_INFLIGHT) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
	} else {
865
		uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
866
867
868
869
		uas_try_complete(cmnd, __func__);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = SUCCESS;
	}
870
	return ret;
Matthew Wilcox's avatar
Matthew Wilcox committed
871
872
}

873
static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
874
{
875
876
877
	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
878
879
880
881
882
883
884
}

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;
885
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
886

Hans de Goede's avatar
Hans de Goede committed
887
888
889
890
891
892
893
	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
894
	shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
895
	devinfo->resetting = 1;
896
	uas_abort_inflight(devinfo, DID_RESET, __func__);
897
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
898
899
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
900
	uas_zap_dead(devinfo);
901
902
	err = usb_reset_device(udev);
	devinfo->resetting = 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
903

Hans de Goede's avatar
Hans de Goede committed
904
905
	usb_unlock_device(udev);

906
907
908
909
	if (err) {
		shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
		return FAILED;
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
910

911
912
	shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__);
	return SUCCESS;
Matthew Wilcox's avatar
Matthew Wilcox committed
913
914
915
916
}

static int uas_slave_alloc(struct scsi_device *sdev)
{
Hans de Goede's avatar
Hans de Goede committed
917
	sdev->hostdata = (void *)sdev->host->hostdata;
Matthew Wilcox's avatar
Matthew Wilcox committed
918
919
920
921
922
923
924
	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);
925
	scsi_activate_tcq(sdev, devinfo->qdepth - 2);
Matthew Wilcox's avatar
Matthew Wilcox committed
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
	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,
};

946
947
948
949
950
951
#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
952
static struct usb_device_id uas_usb_ids[] = {
953
#	include "unusual_uas.h"
Matthew Wilcox's avatar
Matthew Wilcox committed
954
955
956
957
958
959
960
961
	{ 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);

962
963
#undef UNUSUAL_DEV

964
965
966
967
968
969
970
971
972
973
974
975
976
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);
}

977
static int uas_configure_endpoints(struct uas_dev_info *devinfo)
978
979
980
981
982
983
984
985
986
{
	struct usb_host_endpoint *eps[4] = { };
	struct usb_device *udev = devinfo->udev;
	int r;

	devinfo->uas_sense_old = 0;
	devinfo->cmnd = NULL;

	r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
987
988
989
990
991
992
993
994
995
996
997
	if (r