uas.c 28.9 KB
Newer Older
M
Matthew Wilcox 已提交
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>
M
Matthew Wilcox 已提交
15
#include <linux/usb.h>
16
#include <linux/usb/hcd.h>
M
Matthew Wilcox 已提交
17
#include <linux/usb/storage.h>
18
#include <linux/usb/uas.h>
M
Matthew Wilcox 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <scsi/scsi.h>
#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>

/*
 * 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;
44
	struct usb_anchor cmd_urbs;
45 46
	struct usb_anchor sense_urbs;
	struct usb_anchor data_urbs;
G
Gerd Hoffmann 已提交
47 48
	int qdepth, resetting;
	struct response_ui response;
M
Matthew Wilcox 已提交
49 50 51
	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
	unsigned use_streams:1;
	unsigned uas_sense_old:1;
52
	struct scsi_cmnd *cmnd;
G
Gerd Hoffmann 已提交
53
	spinlock_t lock;
M
Matthew Wilcox 已提交
54 55 56
};

enum {
57
	SUBMIT_STATUS_URB	= (1 << 1),
M
Matthew Wilcox 已提交
58 59 60 61 62 63
	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),
64 65 66 67
	COMMAND_INFLIGHT        = (1 << 8),
	DATA_IN_URB_INFLIGHT    = (1 << 9),
	DATA_OUT_URB_INFLIGHT   = (1 << 10),
	COMMAND_COMPLETED       = (1 << 11),
68
	COMMAND_ABORTED         = (1 << 12),
G
Gerd Hoffmann 已提交
69
	UNLINK_DATA_URBS        = (1 << 13),
G
Gerd Hoffmann 已提交
70
	IS_IN_WORK_LIST         = (1 << 14),
M
Matthew Wilcox 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
};

/* 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;
	struct list_head list;
};

/* 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);
86
static void uas_do_work(struct work_struct *work);
G
Gerd Hoffmann 已提交
87
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
M
Matthew Wilcox 已提交
88

89
static DECLARE_WORK(uas_work, uas_do_work);
M
Matthew Wilcox 已提交
90 91 92
static DEFINE_SPINLOCK(uas_work_lock);
static LIST_HEAD(uas_work_list);

93 94 95
static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
				 struct uas_cmd_info *cmdinfo)
{
G
Gerd Hoffmann 已提交
96 97 98 99 100 101 102 103 104 105 106
	unsigned long flags;

	/*
	 * The UNLINK_DATA_URBS flag makes sure uas_try_complete
	 * (called by urb completion) doesn't release cmdinfo
	 * underneath us.
	 */
	spin_lock_irqsave(&devinfo->lock, flags);
	cmdinfo->state |= UNLINK_DATA_URBS;
	spin_unlock_irqrestore(&devinfo->lock, flags);

107 108 109 110
	if (cmdinfo->data_in_urb)
		usb_unlink_urb(cmdinfo->data_in_urb);
	if (cmdinfo->data_out_urb)
		usb_unlink_urb(cmdinfo->data_out_urb);
G
Gerd Hoffmann 已提交
111 112 113 114

	spin_lock_irqsave(&devinfo->lock, flags);
	cmdinfo->state &= ~UNLINK_DATA_URBS;
	spin_unlock_irqrestore(&devinfo->lock, flags);
115 116
}

M
Matthew Wilcox 已提交
117 118 119
static void uas_do_work(struct work_struct *work)
{
	struct uas_cmd_info *cmdinfo;
120
	struct uas_cmd_info *temp;
M
Matthew Wilcox 已提交
121
	struct list_head list;
G
Gerd Hoffmann 已提交
122
	unsigned long flags;
123
	int err;
M
Matthew Wilcox 已提交
124 125 126 127 128

	spin_lock_irq(&uas_work_lock);
	list_replace_init(&uas_work_list, &list);
	spin_unlock_irq(&uas_work_lock);

129
	list_for_each_entry_safe(cmdinfo, temp, &list, list) {
M
Matthew Wilcox 已提交
130 131 132
		struct scsi_pointer *scp = (void *)cmdinfo;
		struct scsi_cmnd *cmnd = container_of(scp,
							struct scsi_cmnd, SCp);
G
Gerd Hoffmann 已提交
133 134 135
		struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
		spin_lock_irqsave(&devinfo->lock, flags);
		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
G
Gerd Hoffmann 已提交
136 137
		if (!err)
			cmdinfo->state &= ~IS_IN_WORK_LIST;
G
Gerd Hoffmann 已提交
138
		spin_unlock_irqrestore(&devinfo->lock, flags);
139 140 141 142 143 144 145
		if (err) {
			list_del(&cmdinfo->list);
			spin_lock_irq(&uas_work_lock);
			list_add_tail(&cmdinfo->list, &uas_work_list);
			spin_unlock_irq(&uas_work_lock);
			schedule_work(&uas_work);
		}
M
Matthew Wilcox 已提交
146 147 148
	}
}

G
Gerd Hoffmann 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
static void uas_abort_work(struct uas_dev_info *devinfo)
{
	struct uas_cmd_info *cmdinfo;
	struct uas_cmd_info *temp;
	struct list_head list;
	unsigned long flags;

	spin_lock_irq(&uas_work_lock);
	list_replace_init(&uas_work_list, &list);
	spin_unlock_irq(&uas_work_lock);

	spin_lock_irqsave(&devinfo->lock, flags);
	list_for_each_entry_safe(cmdinfo, temp, &list, list) {
		struct scsi_pointer *scp = (void *)cmdinfo;
		struct scsi_cmnd *cmnd = container_of(scp,
							struct scsi_cmnd, SCp);
		struct uas_dev_info *di = (void *)cmnd->device->hostdata;

		if (di == devinfo) {
			cmdinfo->state |= COMMAND_ABORTED;
			cmdinfo->state &= ~IS_IN_WORK_LIST;
			if (devinfo->resetting) {
				/* uas_stat_cmplt() will not do that
				 * when a device reset is in
				 * progress */
				cmdinfo->state &= ~COMMAND_INFLIGHT;
			}
			uas_try_complete(cmnd, __func__);
		} else {
			/* not our uas device, relink into list */
			list_del(&cmdinfo->list);
			spin_lock_irq(&uas_work_lock);
			list_add_tail(&cmdinfo->list, &uas_work_list);
			spin_unlock_irq(&uas_work_lock);
		}
	}
	spin_unlock_irqrestore(&devinfo->lock, flags);
}

M
Matthew Wilcox 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
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;
232 233 234 235 236 237 238
}

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:"
G
Gerd Hoffmann 已提交
239
		    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
240 241 242 243 244 245 246 247 248 249 250
		    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"   : "",
251
		    (ci->state & COMMAND_COMPLETED)     ? " done"  : "",
G
Gerd Hoffmann 已提交
252
		    (ci->state & COMMAND_ABORTED)       ? " abort" : "",
G
Gerd Hoffmann 已提交
253 254
		    (ci->state & UNLINK_DATA_URBS)      ? " unlink": "",
		    (ci->state & IS_IN_WORK_LIST)       ? " work"  : "");
255 256 257 258 259
}

static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
G
Gerd Hoffmann 已提交
260
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
261

G
Gerd Hoffmann 已提交
262
	WARN_ON(!spin_is_locked(&devinfo->lock));
263 264
	if (cmdinfo->state & (COMMAND_INFLIGHT |
			      DATA_IN_URB_INFLIGHT |
G
Gerd Hoffmann 已提交
265 266
			      DATA_OUT_URB_INFLIGHT |
			      UNLINK_DATA_URBS))
267 268 269 270 271
		return -EBUSY;
	BUG_ON(cmdinfo->state & COMMAND_COMPLETED);
	cmdinfo->state |= COMMAND_COMPLETED;
	usb_free_urb(cmdinfo->data_in_urb);
	usb_free_urb(cmdinfo->data_out_urb);
G
Gerd Hoffmann 已提交
272 273 274 275
	if (cmdinfo->state & COMMAND_ABORTED) {
		scmd_printk(KERN_INFO, cmnd, "abort completed\n");
		cmnd->result = DID_ABORT << 16;
	}
276
	cmnd->scsi_done(cmnd);
277
	return 0;
M
Matthew Wilcox 已提交
278 279 280
}

static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
281
			  unsigned direction)
M
Matthew Wilcox 已提交
282 283 284 285
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
	int err;

286
	cmdinfo->state |= direction | SUBMIT_STATUS_URB;
M
Matthew Wilcox 已提交
287 288 289 290
	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
	if (err) {
		spin_lock(&uas_work_lock);
		list_add_tail(&cmdinfo->list, &uas_work_list);
G
Gerd Hoffmann 已提交
291
		cmdinfo->state |= IS_IN_WORK_LIST;
M
Matthew Wilcox 已提交
292 293 294 295 296 297 298 299
		spin_unlock(&uas_work_lock);
		schedule_work(&uas_work);
	}
}

static void uas_stat_cmplt(struct urb *urb)
{
	struct iu *iu = urb->transfer_buffer;
300 301
	struct Scsi_Host *shost = urb->context;
	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
M
Matthew Wilcox 已提交
302
	struct scsi_cmnd *cmnd;
303
	struct uas_cmd_info *cmdinfo;
G
Gerd Hoffmann 已提交
304
	unsigned long flags;
M
Matthew Wilcox 已提交
305 306 307 308
	u16 tag;

	if (urb->status) {
		dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
309
		usb_free_urb(urb);
M
Matthew Wilcox 已提交
310 311 312
		return;
	}

G
Gerd Hoffmann 已提交
313 314 315 316 317
	if (devinfo->resetting) {
		usb_free_urb(urb);
		return;
	}

G
Gerd Hoffmann 已提交
318
	spin_lock_irqsave(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
319
	tag = be16_to_cpup(&iu->tag) - 1;
320 321
	if (tag == 0)
		cmnd = devinfo->cmnd;
M
Matthew Wilcox 已提交
322
	else
323
		cmnd = scsi_host_find_tag(shost, tag - 1);
G
Gerd Hoffmann 已提交
324

325
	if (!cmnd) {
G
Gerd Hoffmann 已提交
326 327 328
		if (iu->iu_id == IU_ID_RESPONSE) {
			/* store results for uas_eh_task_mgmt() */
			memcpy(&devinfo->response, iu, sizeof(devinfo->response));
G
Gerd Hoffmann 已提交
329
		}
G
Gerd Hoffmann 已提交
330 331 332
		usb_free_urb(urb);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		return;
333
	}
M
Matthew Wilcox 已提交
334

G
Gerd Hoffmann 已提交
335
	cmdinfo = (void *)&cmnd->SCp;
M
Matthew Wilcox 已提交
336 337
	switch (iu->iu_id) {
	case IU_ID_STATUS:
338 339 340
		if (devinfo->cmnd == cmnd)
			devinfo->cmnd = NULL;

M
Matthew Wilcox 已提交
341 342 343 344 345 346
		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);
G
Gerd Hoffmann 已提交
347 348
		if (cmnd->result != 0) {
			/* cancel data transfers on error */
349 350 351
			spin_unlock_irqrestore(&devinfo->lock, flags);
			uas_unlink_data_urbs(devinfo, cmdinfo);
			spin_lock_irqsave(&devinfo->lock, flags);
G
Gerd Hoffmann 已提交
352
		}
353 354
		cmdinfo->state &= ~COMMAND_INFLIGHT;
		uas_try_complete(cmnd, __func__);
M
Matthew Wilcox 已提交
355 356 357 358 359 360 361 362 363 364 365
		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);
	}
G
Gerd Hoffmann 已提交
366
	usb_free_urb(urb);
G
Gerd Hoffmann 已提交
367
	spin_unlock_irqrestore(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
368 369
}

370
static void uas_data_cmplt(struct urb *urb)
M
Matthew Wilcox 已提交
371
{
372 373
	struct scsi_cmnd *cmnd = urb->context;
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
G
Gerd Hoffmann 已提交
374
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
375
	struct scsi_data_buffer *sdb = NULL;
G
Gerd Hoffmann 已提交
376
	unsigned long flags;
377

G
Gerd Hoffmann 已提交
378
	spin_lock_irqsave(&devinfo->lock, flags);
379 380 381 382 383 384 385 386
	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;
	}
	BUG_ON(sdb == NULL);
G
Gerd Hoffmann 已提交
387 388 389 390 391 392
	if (urb->status) {
		/* error: no data transfered */
		sdb->resid = sdb->length;
	} else {
		sdb->resid = sdb->length - urb->actual_length;
	}
393
	uas_try_complete(cmnd, __func__);
G
Gerd Hoffmann 已提交
394
	spin_unlock_irqrestore(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
395 396 397
}

static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
398 399 400
				      unsigned int pipe, u16 stream_id,
				      struct scsi_cmnd *cmnd,
				      enum dma_data_direction dir)
M
Matthew Wilcox 已提交
401 402 403
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
404 405
	struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
		? scsi_in(cmnd) : scsi_out(cmnd);
M
Matthew Wilcox 已提交
406 407 408

	if (!urb)
		goto out;
409 410
	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
			  uas_data_cmplt, cmnd);
411 412
	if (devinfo->use_streams)
		urb->stream_id = stream_id;
M
Matthew Wilcox 已提交
413 414 415 416 417 418 419
	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,
G
Gerd Hoffmann 已提交
420
				       struct Scsi_Host *shost, u16 stream_id)
M
Matthew Wilcox 已提交
421 422 423 424 425 426 427 428
{
	struct usb_device *udev = devinfo->udev;
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct sense_iu *iu;

	if (!urb)
		goto out;

429
	iu = kzalloc(sizeof(*iu), gfp);
M
Matthew Wilcox 已提交
430 431 432 433
	if (!iu)
		goto free;

	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
G
Gerd Hoffmann 已提交
434
						uas_stat_cmplt, shost);
M
Matthew Wilcox 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
	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,
					struct scsi_cmnd *cmnd, u16 stream_id)
{
	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);
460
	iu = kzalloc(sizeof(*iu) + len, gfp);
M
Matthew Wilcox 已提交
461 462 463 464
	if (!iu)
		goto free;

	iu->iu_id = IU_ID_COMMAND;
465
	if (blk_rq_tagged(cmnd->request))
466
		iu->tag = cpu_to_be16(cmnd->request->tag + 2);
467 468
	else
		iu->tag = cpu_to_be16(1);
C
Christoph Hellwig 已提交
469
	iu->prio_attr = UAS_SIMPLE_TAG;
M
Matthew Wilcox 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483
	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,
							usb_free_urb, NULL);
	urb->transfer_flags |= URB_FREE_BUFFER;
 out:
	return urb;
 free:
	usb_free_urb(urb);
	return NULL;
}

G
Gerd Hoffmann 已提交
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
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),
			  usb_free_urb, NULL);
	urb->transfer_flags |= URB_FREE_BUFFER;

	err = usb_submit_urb(urb, gfp);
	if (err)
		goto err;
521
	usb_anchor_urb(urb, &devinfo->cmd_urbs);
G
Gerd Hoffmann 已提交
522 523 524 525 526 527 528 529

	return 0;

err:
	usb_free_urb(urb);
	return err;
}

M
Matthew Wilcox 已提交
530 531 532 533 534 535
/*
 * 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.
 */

G
Gerd Hoffmann 已提交
536 537
static int uas_submit_sense_urb(struct Scsi_Host *shost,
				gfp_t gfp, unsigned int stream)
M
Matthew Wilcox 已提交
538
{
G
Gerd Hoffmann 已提交
539 540
	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
	struct urb *urb;
M
Matthew Wilcox 已提交
541

G
Gerd Hoffmann 已提交
542 543 544 545 546 547 548 549
	urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
	if (!urb)
		return SCSI_MLQUEUE_DEVICE_BUSY;
	if (usb_submit_urb(urb, gfp)) {
		shost_printk(KERN_INFO, shost,
			     "sense urb submission failure\n");
		usb_free_urb(urb);
		return SCSI_MLQUEUE_DEVICE_BUSY;
M
Matthew Wilcox 已提交
550
	}
551
	usb_anchor_urb(urb, &devinfo->sense_urbs);
G
Gerd Hoffmann 已提交
552 553 554 555 556 557 558 559
	return 0;
}

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;
	int err;
M
Matthew Wilcox 已提交
560

G
Gerd Hoffmann 已提交
561
	WARN_ON(!spin_is_locked(&devinfo->lock));
562
	if (cmdinfo->state & SUBMIT_STATUS_URB) {
G
Gerd Hoffmann 已提交
563 564 565 566
		err = uas_submit_sense_urb(cmnd->device->host, gfp,
					   cmdinfo->stream);
		if (err) {
			return err;
M
Matthew Wilcox 已提交
567
		}
568
		cmdinfo->state &= ~SUBMIT_STATUS_URB;
M
Matthew Wilcox 已提交
569 570 571 572
	}

	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
573
					devinfo->data_in_pipe, cmdinfo->stream,
574
					cmnd, DMA_FROM_DEVICE);
M
Matthew Wilcox 已提交
575 576 577 578 579 580 581 582 583 584 585 586
		if (!cmdinfo->data_in_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
		if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
			scmd_printk(KERN_INFO, cmnd,
					"data in urb submission failure\n");
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
587
		cmdinfo->state |= DATA_IN_URB_INFLIGHT;
588
		usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
M
Matthew Wilcox 已提交
589 590 591 592
	}

	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
593
					devinfo->data_out_pipe, cmdinfo->stream,
594
					cmnd, DMA_TO_DEVICE);
M
Matthew Wilcox 已提交
595 596 597 598 599 600 601 602 603 604 605 606
		if (!cmdinfo->data_out_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
		if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
			scmd_printk(KERN_INFO, cmnd,
					"data out urb submission failure\n");
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
607
		cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
608
		usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
M
Matthew Wilcox 已提交
609 610 611 612
	}

	if (cmdinfo->state & ALLOC_CMD_URB) {
		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
613
						     cmdinfo->stream);
M
Matthew Wilcox 已提交
614 615 616 617 618 619
		if (!cmdinfo->cmd_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_CMD_URB;
	}

	if (cmdinfo->state & SUBMIT_CMD_URB) {
620
		usb_get_urb(cmdinfo->cmd_urb);
M
Matthew Wilcox 已提交
621 622 623 624 625
		if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
			scmd_printk(KERN_INFO, cmnd,
					"cmd urb submission failure\n");
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
626 627 628
		usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
		usb_put_urb(cmdinfo->cmd_urb);
		cmdinfo->cmd_urb = NULL;
M
Matthew Wilcox 已提交
629
		cmdinfo->state &= ~SUBMIT_CMD_URB;
630
		cmdinfo->state |= COMMAND_INFLIGHT;
M
Matthew Wilcox 已提交
631 632 633 634 635
	}

	return 0;
}

J
Jeff Garzik 已提交
636
static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
M
Matthew Wilcox 已提交
637 638 639 640 641
					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;
G
Gerd Hoffmann 已提交
642
	unsigned long flags;
M
Matthew Wilcox 已提交
643 644 645 646
	int err;

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

G
Gerd Hoffmann 已提交
647 648 649
	spin_lock_irqsave(&devinfo->lock, flags);
	if (devinfo->cmnd) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
650
		return SCSI_MLQUEUE_DEVICE_BUSY;
G
Gerd Hoffmann 已提交
651
	}
M
Matthew Wilcox 已提交
652 653

	if (blk_rq_tagged(cmnd->request)) {
654
		cmdinfo->stream = cmnd->request->tag + 2;
M
Matthew Wilcox 已提交
655
	} else {
656
		devinfo->cmnd = cmnd;
M
Matthew Wilcox 已提交
657 658 659 660 661
		cmdinfo->stream = 1;
	}

	cmnd->scsi_done = done;

G
Gerd Hoffmann 已提交
662
	cmdinfo->state = SUBMIT_STATUS_URB |
M
Matthew Wilcox 已提交
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
			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) {
678
		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
M
Matthew Wilcox 已提交
679 680 681 682 683 684
		cmdinfo->stream = 0;
	}

	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
	if (err) {
		/* If we did nothing, give up now */
685
		if (cmdinfo->state & SUBMIT_STATUS_URB) {
G
Gerd Hoffmann 已提交
686
			spin_unlock_irqrestore(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
687 688 689 690
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		spin_lock(&uas_work_lock);
		list_add_tail(&cmdinfo->list, &uas_work_list);
G
Gerd Hoffmann 已提交
691
		cmdinfo->state |= IS_IN_WORK_LIST;
M
Matthew Wilcox 已提交
692 693 694 695
		spin_unlock(&uas_work_lock);
		schedule_work(&uas_work);
	}

G
Gerd Hoffmann 已提交
696
	spin_unlock_irqrestore(&devinfo->lock, flags);
M
Matthew Wilcox 已提交
697 698 699
	return 0;
}

J
Jeff Garzik 已提交
700 701
static DEF_SCSI_QCMD(uas_queuecommand)

G
Gerd Hoffmann 已提交
702 703
static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
			    const char *fname, u8 function)
M
Matthew Wilcox 已提交
704
{
G
Gerd Hoffmann 已提交
705 706
	struct Scsi_Host *shost = cmnd->device->host;
	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
G
Gerd Hoffmann 已提交
707
	u16 tag = devinfo->qdepth - 1;
G
Gerd Hoffmann 已提交
708
	unsigned long flags;
M
Matthew Wilcox 已提交
709

G
Gerd Hoffmann 已提交
710
	spin_lock_irqsave(&devinfo->lock, flags);
G
Gerd Hoffmann 已提交
711
	memset(&devinfo->response, 0, sizeof(devinfo->response));
G
Gerd Hoffmann 已提交
712
	if (uas_submit_sense_urb(shost, GFP_ATOMIC, tag)) {
G
Gerd Hoffmann 已提交
713 714 715
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit sense urb failed\n",
			     __func__, fname);
G
Gerd Hoffmann 已提交
716
		spin_unlock_irqrestore(&devinfo->lock, flags);
G
Gerd Hoffmann 已提交
717 718
		return FAILED;
	}
G
Gerd Hoffmann 已提交
719
	if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) {
G
Gerd Hoffmann 已提交
720 721 722
		shost_printk(KERN_INFO, shost,
			     "%s: %s: submit task mgmt urb failed\n",
			     __func__, fname);
G
Gerd Hoffmann 已提交
723
		spin_unlock_irqrestore(&devinfo->lock, flags);
G
Gerd Hoffmann 已提交
724 725
		return FAILED;
	}
G
Gerd Hoffmann 已提交
726 727 728
	spin_unlock_irqrestore(&devinfo->lock, flags);

	if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
G
Gerd Hoffmann 已提交
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
		shost_printk(KERN_INFO, shost,
			     "%s: %s timed out\n", __func__, fname);
		return FAILED;
	}
	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);
		return FAILED;
	}
	if (devinfo->response.response_code != RC_TMF_COMPLETE) {
		shost_printk(KERN_INFO, shost,
			     "%s: %s failed (rc 0x%x)\n", __func__,
			     fname, devinfo->response.response_code);
		return FAILED;
	}
	return SUCCESS;
M
Matthew Wilcox 已提交
746 747
}

G
Gerd Hoffmann 已提交
748
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
M
Matthew Wilcox 已提交
749
{
G
Gerd Hoffmann 已提交
750
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
G
Gerd Hoffmann 已提交
751 752
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
	unsigned long flags;
G
Gerd Hoffmann 已提交
753
	int ret;
M
Matthew Wilcox 已提交
754

G
Gerd Hoffmann 已提交
755
	uas_log_cmd_state(cmnd, __func__);
G
Gerd Hoffmann 已提交
756
	spin_lock_irqsave(&devinfo->lock, flags);
757
	cmdinfo->state |= COMMAND_ABORTED;
G
Gerd Hoffmann 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
	if (cmdinfo->state & IS_IN_WORK_LIST) {
		spin_lock(&uas_work_lock);
		list_del(&cmdinfo->list);
		cmdinfo->state &= ~IS_IN_WORK_LIST;
		spin_unlock(&uas_work_lock);
	}
	if (cmdinfo->state & COMMAND_INFLIGHT) {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
	} else {
		spin_unlock_irqrestore(&devinfo->lock, flags);
		uas_unlink_data_urbs(devinfo, cmdinfo);
		spin_lock_irqsave(&devinfo->lock, flags);
		uas_try_complete(cmnd, __func__);
		spin_unlock_irqrestore(&devinfo->lock, flags);
		ret = SUCCESS;
	}
G
Gerd Hoffmann 已提交
775
	return ret;
M
Matthew Wilcox 已提交
776 777
}

G
Gerd Hoffmann 已提交
778
static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
M
Matthew Wilcox 已提交
779
{
G
Gerd Hoffmann 已提交
780 781 782
	sdev_printk(KERN_INFO, cmnd->device, "%s\n", __func__);
	return uas_eh_task_mgmt(cmnd, "LOGICAL UNIT RESET",
				TMF_LOGICAL_UNIT_RESET);
M
Matthew Wilcox 已提交
783 784 785 786 787 788 789
}

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;
G
Gerd Hoffmann 已提交
790
	int err;
M
Matthew Wilcox 已提交
791

G
Gerd Hoffmann 已提交
792
	devinfo->resetting = 1;
G
Gerd Hoffmann 已提交
793
	uas_abort_work(devinfo);
794
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
G
Gerd Hoffmann 已提交
795 796 797 798
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
	err = usb_reset_device(udev);
	devinfo->resetting = 0;
M
Matthew Wilcox 已提交
799

G
Gerd Hoffmann 已提交
800 801 802 803
	if (err) {
		shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
		return FAILED;
	}
M
Matthew Wilcox 已提交
804

G
Gerd Hoffmann 已提交
805 806
	shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__);
	return SUCCESS;
M
Matthew Wilcox 已提交
807 808 809 810 811 812 813 814 815 816 817 818
}

static int uas_slave_alloc(struct scsi_device *sdev)
{
	sdev->hostdata = (void *)sdev->host->hostdata[0];
	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);
G
Gerd Hoffmann 已提交
819
	scsi_activate_tcq(sdev, devinfo->qdepth - 3);
M
Matthew Wilcox 已提交
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
	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,
};

static struct usb_device_id uas_usb_ids[] = {
	{ 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);

849 850 851 852 853 854 855
static int uas_is_interface(struct usb_host_interface *intf)
{
	return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
		intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
		intf->desc.bInterfaceProtocol == USB_PR_UAS);
}

856 857 858 859 860 861 862 863 864 865 866 867
static int uas_isnt_supported(struct usb_device *udev)
{
	struct usb_hcd *hcd = bus_to_hcd(udev->bus);

	dev_warn(&udev->dev, "The driver for the USB controller %s does not "
			"support scatter-gather which is\n",
			hcd->driver->description);
	dev_warn(&udev->dev, "required by the UAS driver. Please try an"
			"alternative USB controller if you wish to use UAS.\n");
	return -ENODEV;
}

868 869 870 871
static int uas_switch_interface(struct usb_device *udev,
						struct usb_interface *intf)
{
	int i;
872
	int sg_supported = udev->bus->sg_tablesize != 0;
873 874 875

	for (i = 0; i < intf->num_altsetting; i++) {
		struct usb_host_interface *alt = &intf->altsetting[i];
876 877 878 879

		if (uas_is_interface(alt)) {
			if (!sg_supported)
				return uas_isnt_supported(udev);
880 881 882
			return usb_set_interface(udev,
						alt->desc.bInterfaceNumber,
						alt->desc.bAlternateSetting);
883
		}
884 885 886 887 888
	}

	return -ENODEV;
}

M
Matthew Wilcox 已提交
889 890 891 892 893 894 895 896 897
static void uas_configure_endpoints(struct uas_dev_info *devinfo)
{
	struct usb_host_endpoint *eps[4] = { };
	struct usb_interface *intf = devinfo->intf;
	struct usb_device *udev = devinfo->udev;
	struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
	unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;

	devinfo->uas_sense_old = 0;
898
	devinfo->cmnd = NULL;
M
Matthew Wilcox 已提交
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949

	for (i = 0; i < n_endpoints; i++) {
		unsigned char *extra = endpoint[i].extra;
		int len = endpoint[i].extralen;
		while (len > 1) {
			if (extra[1] == USB_DT_PIPE_USAGE) {
				unsigned pipe_id = extra[2];
				if (pipe_id > 0 && pipe_id < 5)
					eps[pipe_id - 1] = &endpoint[i];
				break;
			}
			len -= extra[0];
			extra += extra[0];
		}
	}

	/*
	 * Assume that if we didn't find a control pipe descriptor, we're
	 * using a device with old firmware that happens to be set up like
	 * this.
	 */
	if (!eps[0]) {
		devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
		devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
		devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
		devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);

		eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
		eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
		eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
	} else {
		devinfo->cmd_pipe = usb_sndbulkpipe(udev,
						eps[0]->desc.bEndpointAddress);
		devinfo->status_pipe = usb_rcvbulkpipe(udev,
						eps[1]->desc.bEndpointAddress);
		devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
						eps[2]->desc.bEndpointAddress);
		devinfo->data_out_pipe = usb_sndbulkpipe(udev,
						eps[3]->desc.bEndpointAddress);
	}

	devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
								GFP_KERNEL);
	if (devinfo->qdepth < 0) {
		devinfo->qdepth = 256;
		devinfo->use_streams = 0;
	} else {
		devinfo->use_streams = 1;
	}
}

950 951 952 953 954 955 956 957 958 959 960
static void uas_free_streams(struct uas_dev_info *devinfo)
{
	struct usb_device *udev = devinfo->udev;
	struct usb_host_endpoint *eps[3];

	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
	usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
}

M
Matthew Wilcox 已提交
961 962 963 964 965 966 967 968 969 970 971 972 973
/*
 * XXX: What I'd like to do here is register a SCSI host for each USB host in
 * the system.  Follow usb-storage's design of registering a SCSI host for
 * each USB device for the moment.  Can implement this by walking up the
 * USB hierarchy until we find a USB host.
 */
static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	int result;
	struct Scsi_Host *shost;
	struct uas_dev_info *devinfo;
	struct usb_device *udev = interface_to_usbdev(intf);

974 975
	if (uas_switch_interface(udev, intf))
		return -ENODEV;
M
Matthew Wilcox 已提交
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991

	devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
	if (!devinfo)
		return -ENOMEM;

	result = -ENOMEM;
	shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
	if (!shost)
		goto free;

	shost->max_cmd_len = 16 + 252;
	shost->max_id = 1;
	shost->sg_tablesize = udev->bus->sg_tablesize;

	devinfo->intf = intf;
	devinfo->udev = udev;
G
Gerd Hoffmann 已提交
992
	devinfo->resetting = 0;
993
	init_usb_anchor(&devinfo->cmd_urbs);
994 995
	init_usb_anchor(&devinfo->sense_urbs);
	init_usb_anchor(&devinfo->data_urbs);
G
Gerd Hoffmann 已提交
996
	spin_lock_init(&devinfo->lock);
M
Matthew Wilcox 已提交
997 998
	uas_configure_endpoints(devinfo);

G
Gerd Hoffmann 已提交
999
	result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3);
M
Matthew Wilcox 已提交
1000 1001
	if (result)
		goto free;
1002 1003 1004 1005 1006

	result = scsi_add_host(shost, &intf->dev);
	if (result)
		goto deconfig_eps;

M
Matthew Wilcox 已提交
1007 1008 1009 1010 1011
	shost->hostdata[0] = (unsigned long)devinfo;

	scsi_scan_host(shost);
	usb_set_intfdata(intf, shost);
	return result;
1012 1013 1014

deconfig_eps:
	uas_free_streams(devinfo);
M
Matthew Wilcox 已提交
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
 free:
	kfree(devinfo);
	if (shost)
		scsi_host_put(shost);
	return result;
}

static int uas_pre_reset(struct usb_interface *intf)
{
/* XXX: Need to return 1 if it's not our device in error handling */
	return 0;
}

static int uas_post_reset(struct usb_interface *intf)
{
/* XXX: Need to return 1 if it's not our device in error handling */
	return 0;
}

static void uas_disconnect(struct usb_interface *intf)
{
	struct Scsi_Host *shost = usb_get_intfdata(intf);
	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];

G
Gerd Hoffmann 已提交
1039 1040
	devinfo->resetting = 1;
	uas_abort_work(devinfo);
1041
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
1042 1043
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
G
Gerd Hoffmann 已提交
1044
	scsi_remove_host(shost);
1045
	uas_free_streams(devinfo);
M
Matthew Wilcox 已提交
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
	kfree(devinfo);
}

/*
 * XXX: Should this plug into libusual so we can auto-upgrade devices from
 * Bulk-Only to UAS?
 */
static struct usb_driver uas_driver = {
	.name = "uas",
	.probe = uas_probe,
	.disconnect = uas_disconnect,
	.pre_reset = uas_pre_reset,
	.post_reset = uas_post_reset,
	.id_table = uas_usb_ids,
};

1062
module_usb_driver(uas_driver);
M
Matthew Wilcox 已提交
1063 1064 1065

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");