uas.c 32.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
Matthew Wilcox's avatar
Matthew Wilcox committed
2 3 4 5
/*
 * USB Attached SCSI
 * Note that this is not the same as the USB Mass Storage driver
 *
6
 * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013 - 2016
Matthew Wilcox's avatar
Matthew Wilcox committed
7 8 9 10 11 12 13
 * Copyright Matthew Wilcox for Intel Corp, 2010
 * Copyright Sarah Sharp for Intel Corp, 2010
 */

#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
#include "uas-detect.h"
30
#include "scsiglue.h"
31

32
#define MAX_CMNDS 256
Matthew Wilcox's avatar
Matthew Wilcox committed
33 34 35 36

struct uas_dev_info {
	struct usb_interface *intf;
	struct usb_device *udev;
37
	struct usb_anchor cmd_urbs;
38 39
	struct usb_anchor sense_urbs;
	struct usb_anchor data_urbs;
40
	unsigned long flags;
41
	int qdepth, resetting;
Matthew Wilcox's avatar
Matthew Wilcox committed
42 43
	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
	unsigned use_streams:1;
Hans de Goede's avatar
Hans de Goede committed
44
	unsigned shutdown:1;
45
	struct scsi_cmnd *cmnd[MAX_CMNDS];
Gerd Hoffmann's avatar
Gerd Hoffmann committed
46
	spinlock_t lock;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
47
	struct work_struct work;
EJ Hsu's avatar
EJ Hsu committed
48
	struct work_struct scan_work;      /* for async scanning */
Matthew Wilcox's avatar
Matthew Wilcox committed
49 50 51
};

enum {
Oliver Neukum's avatar
Oliver Neukum committed
52 53 54 55 56 57 58 59 60 61 62 63
	SUBMIT_STATUS_URB	= BIT(1),
	ALLOC_DATA_IN_URB	= BIT(2),
	SUBMIT_DATA_IN_URB	= BIT(3),
	ALLOC_DATA_OUT_URB	= BIT(4),
	SUBMIT_DATA_OUT_URB	= BIT(5),
	ALLOC_CMD_URB		= BIT(6),
	SUBMIT_CMD_URB		= BIT(7),
	COMMAND_INFLIGHT        = BIT(8),
	DATA_IN_URB_INFLIGHT    = BIT(9),
	DATA_OUT_URB_INFLIGHT   = BIT(10),
	COMMAND_ABORTED         = BIT(11),
	IS_IN_WORK_LIST         = BIT(12),
Matthew Wilcox's avatar
Matthew Wilcox committed
64 65 66 67 68
};

/* Overrides scsi_pointer */
struct uas_cmd_info {
	unsigned int state;
Hans de Goede's avatar
Hans de Goede committed
69
	unsigned int uas_tag;
Matthew Wilcox's avatar
Matthew Wilcox committed
70 71 72 73 74 75 76
	struct urb *cmd_urb;
	struct urb *data_in_urb;
	struct urb *data_out_urb;
};

/* I hate forward declarations, but I actually have a loop */
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
77
				struct uas_dev_info *devinfo);
78
static void uas_do_work(struct work_struct *work);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
79
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
80
static void uas_free_streams(struct uas_dev_info *devinfo);
81 82
static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
				int status);
83

Matthew Wilcox's avatar
Matthew Wilcox committed
84 85
static void uas_do_work(struct work_struct *work)
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
86 87
	struct uas_dev_info *devinfo =
		container_of(work, struct uas_dev_info, work);
Matthew Wilcox's avatar
Matthew Wilcox committed
88
	struct uas_cmd_info *cmdinfo;
Hans de Goede's avatar
Hans de Goede committed
89
	struct scsi_cmnd *cmnd;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
90
	unsigned long flags;
Hans de Goede's avatar
Hans de Goede committed
91
	int i, err;
Matthew Wilcox's avatar
Matthew Wilcox committed
92

Gerd Hoffmann's avatar
Gerd Hoffmann committed
93
	spin_lock_irqsave(&devinfo->lock, flags);
94 95 96 97

	if (devinfo->resetting)
		goto out;

Hans de Goede's avatar
Hans de Goede committed
98 99 100 101 102 103
	for (i = 0; i < devinfo->qdepth; i++) {
		if (!devinfo->cmnd[i])
			continue;

		cmnd = devinfo->cmnd[i];
		cmdinfo = (void *)&cmnd->SCp;
104 105 106 107

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

108
		err = uas_submit_urbs(cmnd, cmnd->device->hostdata);
109
		if (!err)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
110
			cmdinfo->state &= ~IS_IN_WORK_LIST;
111
		else
Gerd Hoffmann's avatar
Gerd Hoffmann committed
112
			schedule_work(&devinfo->work);
Matthew Wilcox's avatar
Matthew Wilcox committed
113
	}
114
out:
Gerd Hoffmann's avatar
Gerd Hoffmann committed
115 116 117
	spin_unlock_irqrestore(&devinfo->lock, flags);
}

EJ Hsu's avatar
EJ Hsu committed
118 119 120 121 122 123 124 125 126 127 128
static void uas_scan_work(struct work_struct *work)
{
	struct uas_dev_info *devinfo =
		container_of(work, struct uas_dev_info, scan_work);
	struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf);

	dev_dbg(&devinfo->intf->dev, "starting scan\n");
	scsi_scan_host(shost);
	dev_dbg(&devinfo->intf->dev, "scan complete\n");
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
129 130 131 132 133 134
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;

135
	lockdep_assert_held(&devinfo->lock);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
136 137 138 139
	cmdinfo->state |= IS_IN_WORK_LIST;
	schedule_work(&devinfo->work);
}

140
static void uas_zap_pending(struct uas_dev_info *devinfo, int result)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
141 142
{
	struct uas_cmd_info *cmdinfo;
Hans de Goede's avatar
Hans de Goede committed
143
	struct scsi_cmnd *cmnd;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
144
	unsigned long flags;
Hans de Goede's avatar
Hans de Goede committed
145
	int i, err;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
146 147

	spin_lock_irqsave(&devinfo->lock, flags);
Hans de Goede's avatar
Hans de Goede committed
148 149 150 151 152 153
	for (i = 0; i < devinfo->qdepth; i++) {
		if (!devinfo->cmnd[i])
			continue;

		cmnd = devinfo->cmnd[i];
		cmdinfo = (void *)&cmnd->SCp;
154
		uas_log_cmd_state(cmnd, __func__, 0);
155 156
		/* Sense urbs were killed, clear COMMAND_INFLIGHT manually */
		cmdinfo->state &= ~COMMAND_INFLIGHT;
157
		cmnd->result = result << 16;
158 159
		err = uas_try_complete(cmnd, __func__);
		WARN_ON(err != 0);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
160 161 162 163
	}
	spin_unlock_irqrestore(&devinfo->lock, flags);
}

Matthew Wilcox's avatar
Matthew Wilcox committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
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;
}

187 188
static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
			      int status)
189 190
{
	struct uas_cmd_info *ci = (void *)&cmnd->SCp;
Hans de Goede's avatar
Hans de Goede committed
191
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
192

193 194 195
	if (status == -ENODEV) /* too late */
		return;

196
	scmd_printk(KERN_INFO, cmnd,
Hans de Goede's avatar
Hans de Goede committed
197 198
		    "%s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
		    prefix, status, cmdinfo->uas_tag,
199 200 201 202 203 204 205 206 207 208
		    (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"   : "",
Gerd Hoffmann's avatar
Gerd Hoffmann committed
209
		    (ci->state & COMMAND_ABORTED)       ? " abort" : "",
Gerd Hoffmann's avatar
Gerd Hoffmann committed
210
		    (ci->state & IS_IN_WORK_LIST)       ? " work"  : "");
Hans de Goede's avatar
Hans de Goede committed
211
	scsi_print_command(cmnd);
212 213
}

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd)
{
	struct uas_cmd_info *cmdinfo;

	if (!cmnd)
		return;

	cmdinfo = (void *)&cmnd->SCp;

	if (cmdinfo->state & SUBMIT_CMD_URB)
		usb_free_urb(cmdinfo->cmd_urb);

	/* data urbs may have never gotten their submit flag set */
	if (!(cmdinfo->state & DATA_IN_URB_INFLIGHT))
		usb_free_urb(cmdinfo->data_in_urb);
	if (!(cmdinfo->state & DATA_OUT_URB_INFLIGHT))
		usb_free_urb(cmdinfo->data_out_urb);
231 232 233 234 235
}

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
236
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
237

238
	lockdep_assert_held(&devinfo->lock);
239 240
	if (cmdinfo->state & (COMMAND_INFLIGHT |
			      DATA_IN_URB_INFLIGHT |
Gerd Hoffmann's avatar
Gerd Hoffmann committed
241
			      DATA_OUT_URB_INFLIGHT |
242
			      COMMAND_ABORTED))
243
		return -EBUSY;
Hans de Goede's avatar
Hans de Goede committed
244
	devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
245
	uas_free_unsubmitted_urbs(cmnd);
246
	cmnd->scsi_done(cmnd);
247
	return 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
248 249 250
}

static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
251
			  unsigned direction)
Matthew Wilcox's avatar
Matthew Wilcox committed
252 253 254 255
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
	int err;

256
	cmdinfo->state |= direction | SUBMIT_STATUS_URB;
257
	err = uas_submit_urbs(cmnd, cmnd->device->hostdata);
Matthew Wilcox's avatar
Matthew Wilcox committed
258
	if (err) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
259
		uas_add_work(cmdinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
260 261 262
	}
}

263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *cmnd)
{
	u8 response_code = riu->response_code;

	switch (response_code) {
	case RC_INCORRECT_LUN:
		cmnd->result = DID_BAD_TARGET << 16;
		break;
	case RC_TMF_SUCCEEDED:
		cmnd->result = DID_OK << 16;
		break;
	case RC_TMF_NOT_SUPPORTED:
		cmnd->result = DID_TARGET_FAILURE << 16;
		break;
	default:
		uas_log_cmd_state(cmnd, "response iu", response_code);
		cmnd->result = DID_ERROR << 16;
		break;
	}

	return response_code == RC_TMF_SUCCEEDED;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
286 287 288
static void uas_stat_cmplt(struct urb *urb)
{
	struct iu *iu = urb->transfer_buffer;
289
	struct Scsi_Host *shost = urb->context;
Hans de Goede's avatar
Hans de Goede committed
290
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
291 292
	struct urb *data_in_urb = NULL;
	struct urb *data_out_urb = NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
293
	struct scsi_cmnd *cmnd;
294
	struct uas_cmd_info *cmdinfo;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
295
	unsigned long flags;
296
	unsigned int idx;
297
	int status = urb->status;
298
	bool success;
Matthew Wilcox's avatar
Matthew Wilcox committed
299

300 301 302 303
	spin_lock_irqsave(&devinfo->lock, flags);

	if (devinfo->resetting)
		goto out;
Matthew Wilcox's avatar
Matthew Wilcox committed
304

305 306 307
	if (status) {
		if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
			dev_err(&urb->dev->dev, "stat urb: status %d\n", status);
308
		goto out;
Matthew Wilcox's avatar
Matthew Wilcox committed
309 310
	}

311 312 313
	idx = be16_to_cpup(&iu->tag) - 1;
	if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) {
		dev_err(&urb->dev->dev,
Hans de Goede's avatar
Hans de Goede committed
314
			"stat urb: no pending cmd for uas-tag %d\n", idx + 1);
315
		goto out;
316 317
	}

318
	cmnd = devinfo->cmnd[idx];
Gerd Hoffmann's avatar
Gerd Hoffmann committed
319
	cmdinfo = (void *)&cmnd->SCp;
320 321

	if (!(cmdinfo->state & COMMAND_INFLIGHT)) {
322
		uas_log_cmd_state(cmnd, "unexpected status cmplt", 0);
323
		goto out;
324
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
325 326 327

	switch (iu->iu_id) {
	case IU_ID_STATUS:
328
		uas_sense(urb, cmnd);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
329 330
		if (cmnd->result != 0) {
			/* cancel data transfers on error */
331 332
			data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
			data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
333
		}
334 335
		cmdinfo->state &= ~COMMAND_INFLIGHT;
		uas_try_complete(cmnd, __func__);
Matthew Wilcox's avatar
Matthew Wilcox committed
336 337
		break;
	case IU_ID_READ_READY:
338 339
		if (!cmdinfo->data_in_urb ||
				(cmdinfo->state & DATA_IN_URB_INFLIGHT)) {
340
			uas_log_cmd_state(cmnd, "unexpected read rdy", 0);
341 342
			break;
		}
Matthew Wilcox's avatar
Matthew Wilcox committed
343 344 345
		uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
		break;
	case IU_ID_WRITE_READY:
346 347
		if (!cmdinfo->data_out_urb ||
				(cmdinfo->state & DATA_OUT_URB_INFLIGHT)) {
348
			uas_log_cmd_state(cmnd, "unexpected write rdy", 0);
349 350
			break;
		}
Matthew Wilcox's avatar
Matthew Wilcox committed
351 352
		uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
		break;
Hans de Goede's avatar
Hans de Goede committed
353 354
	case IU_ID_RESPONSE:
		cmdinfo->state &= ~COMMAND_INFLIGHT;
355 356 357 358 359 360
		success = uas_evaluate_response_iu((struct response_iu *)iu, cmnd);
		if (!success) {
			/* Error, cancel data transfers */
			data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
			data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
		}
Hans de Goede's avatar
Hans de Goede committed
361 362
		uas_try_complete(cmnd, __func__);
		break;
Matthew Wilcox's avatar
Matthew Wilcox committed
363
	default:
364
		uas_log_cmd_state(cmnd, "bogus IU", iu->iu_id);
Matthew Wilcox's avatar
Matthew Wilcox committed
365
	}
366
out:
Gerd Hoffmann's avatar
Gerd Hoffmann committed
367
	usb_free_urb(urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
368
	spin_unlock_irqrestore(&devinfo->lock, flags);
369 370 371 372 373 374 375 376 377 378

	/* Unlinking of data urbs must be done without holding the lock */
	if (data_in_urb) {
		usb_unlink_urb(data_in_urb);
		usb_put_urb(data_in_urb);
	}
	if (data_out_urb) {
		usb_unlink_urb(data_out_urb);
		usb_put_urb(data_out_urb);
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
379 380
}

381
static void uas_data_cmplt(struct urb *urb)
Matthew Wilcox's avatar
Matthew Wilcox committed
382
{
383 384
	struct scsi_cmnd *cmnd = urb->context;
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
385
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
386
	struct scsi_data_buffer *sdb = NULL;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
387
	unsigned long flags;
388
	int status = urb->status;
389

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

392 393 394
	if (cmdinfo->data_in_urb == urb) {
		sdb = scsi_in(cmnd);
		cmdinfo->state &= ~DATA_IN_URB_INFLIGHT;
395
		cmdinfo->data_in_urb = NULL;
396 397 398
	} else if (cmdinfo->data_out_urb == urb) {
		sdb = scsi_out(cmnd);
		cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT;
399
		cmdinfo->data_out_urb = NULL;
400
	}
401 402
	if (sdb == NULL) {
		WARN_ON_ONCE(1);
403 404 405 406 407 408
		goto out;
	}

	if (devinfo->resetting)
		goto out;

409 410
	/* Data urbs should not complete before the cmd urb is submitted */
	if (cmdinfo->state & SUBMIT_CMD_URB) {
411
		uas_log_cmd_state(cmnd, "unexpected data cmplt", 0);
412 413 414
		goto out;
	}

415 416 417
	if (status) {
		if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
			uas_log_cmd_state(cmnd, "data cmplt err", status);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
418 419 420 421 422
		/* error: no data transfered */
		sdb->resid = sdb->length;
	} else {
		sdb->resid = sdb->length - urb->actual_length;
	}
423
	uas_try_complete(cmnd, __func__);
424
out:
425
	usb_free_urb(urb);
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
static void uas_cmd_cmplt(struct urb *urb)
{
431 432
	if (urb->status)
		dev_err(&urb->dev->dev, "cmd cmplt err %d\n", urb->status);
Hans de Goede's avatar
Hans de Goede committed
433 434 435 436

	usb_free_urb(urb);
}

Matthew Wilcox's avatar
Matthew Wilcox committed
437
static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
438 439
				      struct scsi_cmnd *cmnd,
				      enum dma_data_direction dir)
Matthew Wilcox's avatar
Matthew Wilcox committed
440 441
{
	struct usb_device *udev = devinfo->udev;
442
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Matthew Wilcox's avatar
Matthew Wilcox committed
443
	struct urb *urb = usb_alloc_urb(0, gfp);
444 445
	struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
		? scsi_in(cmnd) : scsi_out(cmnd);
446 447
	unsigned int pipe = (dir == DMA_FROM_DEVICE)
		? devinfo->data_in_pipe : devinfo->data_out_pipe;
Matthew Wilcox's avatar
Matthew Wilcox committed
448 449 450

	if (!urb)
		goto out;
451 452
	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
			  uas_data_cmplt, cmnd);
Hans de Goede's avatar
Hans de Goede committed
453 454
	if (devinfo->use_streams)
		urb->stream_id = cmdinfo->uas_tag;
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,
462
				       struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
463 464
{
	struct usb_device *udev = devinfo->udev;
465
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Matthew Wilcox's avatar
Matthew Wilcox committed
466 467 468 469 470 471
	struct urb *urb = usb_alloc_urb(0, gfp);
	struct sense_iu *iu;

	if (!urb)
		goto out;

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

	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
477
			  uas_stat_cmplt, cmnd->device->host);
Hans de Goede's avatar
Hans de Goede committed
478 479
	if (devinfo->use_streams)
		urb->stream_id = cmdinfo->uas_tag;
Matthew Wilcox's avatar
Matthew Wilcox committed
480 481 482 483 484 485 486 487 488
	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,
489
					struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
490 491 492
{
	struct usb_device *udev = devinfo->udev;
	struct scsi_device *sdev = cmnd->device;
Hans de Goede's avatar
Hans de Goede committed
493
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
Matthew Wilcox's avatar
Matthew Wilcox committed
494 495 496 497 498 499 500 501 502 503 504
	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);
505
	iu = kzalloc(sizeof(*iu) + len, gfp);
Matthew Wilcox's avatar
Matthew Wilcox committed
506 507 508 509
	if (!iu)
		goto free;

	iu->iu_id = IU_ID_COMMAND;
Hans de Goede's avatar
Hans de Goede committed
510
	iu->tag = cpu_to_be16(cmdinfo->uas_tag);
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,
517
							uas_cmd_cmplt, NULL);
Matthew Wilcox's avatar
Matthew Wilcox committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531
	urb->transfer_flags |= URB_FREE_BUFFER;
 out:
	return urb;
 free:
	usb_free_urb(urb);
	return NULL;
}

/*
 * 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.
 */

532
static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
Matthew Wilcox's avatar
Matthew Wilcox committed
533
{
534
	struct uas_dev_info *devinfo = cmnd->device->hostdata;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
535
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
536
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
537

538
	urb = uas_alloc_sense_urb(devinfo, gfp, cmnd);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
539
	if (!urb)
540
		return NULL;
541
	usb_anchor_urb(urb, &devinfo->sense_urbs);
Hans de Goede's avatar
Hans de Goede committed
542 543
	err = usb_submit_urb(urb, gfp);
	if (err) {
544
		usb_unanchor_urb(urb);
545
		uas_log_cmd_state(cmnd, "sense submit err", err);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
546
		usb_free_urb(urb);
547
		return NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
548
	}
549
	return urb;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
550 551 552
}

static int uas_submit_urbs(struct scsi_cmnd *cmnd,
553
			   struct uas_dev_info *devinfo)
Gerd Hoffmann's avatar
Gerd Hoffmann committed
554 555
{
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
556
	struct urb *urb;
Hans de Goede's avatar
Hans de Goede committed
557
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
558

559
	lockdep_assert_held(&devinfo->lock);
560
	if (cmdinfo->state & SUBMIT_STATUS_URB) {
561
		urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
562 563
		if (!urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
564
		cmdinfo->state &= ~SUBMIT_STATUS_URB;
Matthew Wilcox's avatar
Matthew Wilcox committed
565 566 567
	}

	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
568
		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
569
							cmnd, DMA_FROM_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
570 571 572 573 574 575
		if (!cmdinfo->data_in_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
576
		usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
577
		err = usb_submit_urb(cmdinfo->data_in_urb, GFP_ATOMIC);
Hans de Goede's avatar
Hans de Goede committed
578
		if (err) {
579
			usb_unanchor_urb(cmdinfo->data_in_urb);
580
			uas_log_cmd_state(cmnd, "data in submit err", err);
Matthew Wilcox's avatar
Matthew Wilcox committed
581 582 583
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
584
		cmdinfo->state |= DATA_IN_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
585 586 587
	}

	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
588
		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
589
							cmnd, DMA_TO_DEVICE);
Matthew Wilcox's avatar
Matthew Wilcox committed
590 591 592 593 594 595
		if (!cmdinfo->data_out_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
	}

	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
596
		usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
597
		err = usb_submit_urb(cmdinfo->data_out_urb, GFP_ATOMIC);
Hans de Goede's avatar
Hans de Goede committed
598
		if (err) {
599
			usb_unanchor_urb(cmdinfo->data_out_urb);
600
			uas_log_cmd_state(cmnd, "data out submit err", err);
Matthew Wilcox's avatar
Matthew Wilcox committed
601 602 603
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
604
		cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
605 606 607
	}

	if (cmdinfo->state & ALLOC_CMD_URB) {
608
		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd);
Matthew Wilcox's avatar
Matthew Wilcox committed
609 610 611 612 613 614
		if (!cmdinfo->cmd_urb)
			return SCSI_MLQUEUE_DEVICE_BUSY;
		cmdinfo->state &= ~ALLOC_CMD_URB;
	}

	if (cmdinfo->state & SUBMIT_CMD_URB) {
615
		usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
616
		err = usb_submit_urb(cmdinfo->cmd_urb, GFP_ATOMIC);
Hans de Goede's avatar
Hans de Goede committed
617
		if (err) {
618
			usb_unanchor_urb(cmdinfo->cmd_urb);
619
			uas_log_cmd_state(cmnd, "cmd submit err", err);
Matthew Wilcox's avatar
Matthew Wilcox committed
620 621
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
622
		cmdinfo->cmd_urb = NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
623
		cmdinfo->state &= ~SUBMIT_CMD_URB;
624
		cmdinfo->state |= COMMAND_INFLIGHT;
Matthew Wilcox's avatar
Matthew Wilcox committed
625 626 627 628 629
	}

	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
630
static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
Matthew Wilcox's avatar
Matthew Wilcox committed
631 632 633 634 635
					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
636
	unsigned long flags;
Hans de Goede's avatar
Hans de Goede committed
637
	int idx, err;
Matthew Wilcox's avatar
Matthew Wilcox committed
638 639 640

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

641 642 643 644
	/* Re-check scsi_block_requests now that we've the host-lock */
	if (cmnd->device->host->host_self_blocked)
		return SCSI_MLQUEUE_DEVICE_BUSY;

645 646 647 648 649 650 651 652 653
	if ((devinfo->flags & US_FL_NO_ATA_1X) &&
			(cmnd->cmnd[0] == ATA_12 || cmnd->cmnd[0] == ATA_16)) {
		memcpy(cmnd->sense_buffer, usb_stor_sense_invalidCDB,
		       sizeof(usb_stor_sense_invalidCDB));
		cmnd->result = SAM_STAT_CHECK_CONDITION;
		cmnd->scsi_done(cmnd);
		return 0;
	}

654 655
	spin_lock_irqsave(&devinfo->lock, flags);

656 657 658
	if (devinfo->resetting) {
		cmnd->result = DID_ERROR << 16;
		cmnd->scsi_done(cmnd);
659
		spin_unlock_irqrestore(&devinfo->lock, flags);
660 661 662
		return 0;
	}

Hans de Goede's avatar
Hans de Goede committed
663 664 665 666 667 668
	/* Find a free uas-tag */
	for (idx = 0; idx < devinfo->qdepth; idx++) {
		if (!devinfo->cmnd[idx])
			break;
	}
	if (idx == devinfo->qdepth) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
669
		spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
670
		return SCSI_MLQUEUE_DEVICE_BUSY;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
671
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
672 673 674

	cmnd->scsi_done = done;

675
	memset(cmdinfo, 0, sizeof(*cmdinfo));
Hans de Goede's avatar
Hans de Goede committed
676
	cmdinfo->uas_tag = idx + 1; /* uas-tag == usb-stream-id, so 1 based */
677
	cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB;
Matthew Wilcox's avatar
Matthew Wilcox committed
678 679 680 681 682 683 684

	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;
685
		/* fall through */
Matthew Wilcox's avatar
Matthew Wilcox committed
686 687 688 689 690 691
	case DMA_TO_DEVICE:
		cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
	case DMA_NONE:
		break;
	}

Hans de Goede's avatar
Hans de Goede committed
692
	if (!devinfo->use_streams)
693
		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
Matthew Wilcox's avatar
Matthew Wilcox committed
694

695
	err = uas_submit_urbs(cmnd, devinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
696 697
	if (err) {
		/* If we did nothing, give up now */
698
		if (cmdinfo->state & SUBMIT_STATUS_URB) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
699
			spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
700 701
			return SCSI_MLQUEUE_DEVICE_BUSY;
		}
Gerd Hoffmann's avatar
Gerd Hoffmann committed
702
		uas_add_work(cmdinfo);
Matthew Wilcox's avatar
Matthew Wilcox committed
703 704
	}

Hans de Goede's avatar
Hans de Goede committed
705
	devinfo->cmnd[idx] = cmnd;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
706
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
707 708 709
	return 0;
}

Jeff Garzik's avatar
Jeff Garzik committed
710 711
static DEF_SCSI_QCMD(uas_queuecommand)

712 713 714 715 716 717
/*
 * For now we do not support actually sending an abort to the device, so
 * this eh always fails. Still we must define it to make sure that we've
 * dropped all references to the cmnd in question once this function exits.
 */
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
718
{
719 720 721 722
	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
	struct urb *data_in_urb = NULL;
	struct urb *data_out_urb = NULL;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
723
	unsigned long flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
724

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

727
	uas_log_cmd_state(cmnd, __func__, 0);
728

729 730
	/* Ensure that try_complete does not call scsi_done */
	cmdinfo->state |= COMMAND_ABORTED;
731

732
	/* Drop all refs to this cmnd, kill data urbs to break their ref */
Hans de Goede's avatar
Hans de Goede committed
733
	devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
734 735 736 737
	if (cmdinfo->state & DATA_IN_URB_INFLIGHT)
		data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
	if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
		data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
738

739
	uas_free_unsubmitted_urbs(cmnd);
740 741 742

	spin_unlock_irqrestore(&devinfo->lock, flags);

743 744 745
	if (data_in_urb) {
		usb_kill_urb(data_in_urb);
		usb_put_urb(data_in_urb);
746
	}
747 748 749
	if (data_out_urb) {
		usb_kill_urb(data_out_urb);
		usb_put_urb(data_out_urb);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
750
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
751

752
	return FAILED;
Matthew Wilcox's avatar
Matthew Wilcox committed
753 754
}

755
static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
Matthew Wilcox's avatar
Matthew Wilcox committed
756 757 758 759
{
	struct scsi_device *sdev = cmnd->device;
	struct uas_dev_info *devinfo = sdev->hostdata;
	struct usb_device *udev = devinfo->udev;
760
	unsigned long flags;
761
	int err;
Matthew Wilcox's avatar
Matthew Wilcox committed
762

Hans de Goede's avatar
Hans de Goede committed
763 764 765 766 767 768 769
	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
770
	shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
771 772

	spin_lock_irqsave(&devinfo->lock, flags);
773
	devinfo->resetting = 1;
774 775
	spin_unlock_irqrestore(&devinfo->lock, flags);

776
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
777 778
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
779 780
	uas_zap_pending(devinfo, DID_RESET);

781
	err = usb_reset_device(udev);
782 783

	spin_lock_irqsave(&devinfo->lock, flags);
784
	devinfo->resetting = 0;
785
	spin_unlock_irqrestore(&devinfo->lock, flags);
Matthew Wilcox's avatar
Matthew Wilcox committed
786

Hans de Goede's avatar
Hans de Goede committed
787 788
	usb_unlock_device(udev);

789
	if (err) {
790 791
		shost_printk(KERN_INFO, sdev->host, "%s FAILED err %d\n",
			     __func__, err);
792 793
		return FAILED;
	}
Matthew Wilcox's avatar
Matthew Wilcox committed
794

795 796
	shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__);
	return SUCCESS;
Matthew Wilcox's avatar
Matthew Wilcox committed
797 798
}

799 800 801 802 803 804 805 806 807 808 809
static int uas_target_alloc(struct scsi_target *starget)
{
	struct uas_dev_info *devinfo = (struct uas_dev_info *)
			dev_to_shost(starget->dev.parent)->hostdata;

	if (devinfo->flags & US_FL_NO_REPORT_LUNS)
		starget->no_report_luns = 1;

	return 0;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
810 811
static int uas_slave_alloc(struct scsi_device *sdev)
{
812 813 814 815
	struct uas_dev_info *devinfo =
		(struct uas_dev_info *)sdev->host->hostdata;

	sdev->hostdata = devinfo;
816

817 818 819 820
	/*
	 * The protocol has no requirements on alignment in the strict sense.
	 * Controllers may or may not have alignment restrictions.
	 * As this is not exported, we use an extremely conservative guess.
821 822 823
	 */
	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));

824 825 826 827 828
	if (devinfo->flags & US_FL_MAX_SECTORS_64)
		blk_queue_max_hw_sectors(sdev->request_queue, 64);
	else if (devinfo->flags & US_FL_MAX_SECTORS_240)
		blk_queue_max_hw_sectors(sdev->request_queue, 240);

Matthew Wilcox's avatar
Matthew Wilcox committed
829 830 831 832 833 834
	return 0;
}

static int uas_slave_configure(struct scsi_device *sdev)
{
	struct uas_dev_info *devinfo = sdev->hostdata;
835 836 837 838

	if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
		sdev->no_report_opcodes = 1;

839 840 841 842
	/* A few buggy USB-ATA bridges don't understand FUA */
	if (devinfo->flags & US_FL_BROKEN_FUA)
		sdev->broken_fua = 1;

843 844 845 846 847 848
	/* UAS also needs to support FL_ALWAYS_SYNC */
	if (devinfo->flags & US_FL_ALWAYS_SYNC) {
		sdev->skip_ms_page_3f = 1;
		sdev->skip_ms_page_8 = 1;
		sdev->wce_default_on = 1;
	}
849

850 851 852 853
	/* Some disks cannot handle READ_CAPACITY_16 */
	if (devinfo->flags & US_FL_NO_READ_CAPACITY_16)
		sdev->no_read_capacity_16 = 1;

854 855 856 857 858 859 860 861
	/*
	 * Some disks return the total number of blocks in response
	 * to READ CAPACITY rather than the highest block number.
	 * If this device makes that mistake, tell the sd driver.
	 */
	if (devinfo->flags & US_FL_FIX_CAPACITY)
		sdev->fix_capacity = 1;

862 863 864 865 866 867
	/*
	 * in some cases we have to guess
	 */
	if (devinfo->flags & US_FL_CAPACITY_HEURISTICS)
		sdev->guess_capacity = 1;

868 869 870 871 872 873 874 875 876 877 878 879
	/*
	 * Some devices don't like MODE SENSE with page=0x3f,
	 * which is the command used for checking if a device
	 * is write-protected.  Now that we tell the sd driver
	 * to do a 192-byte transfer with this command the
	 * majority of devices work fine, but a few still can't
	 * handle it.  The sd driver will simply assume those
	 * devices are write-enabled.
	 */
	if (devinfo->flags & US_FL_NO_WP_DETECT)
		sdev->skip_ms_page_3f = 1;

880
	scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
Matthew Wilcox's avatar
Matthew Wilcox committed
881 882 883 884 885 886 887
	return 0;
}

static struct scsi_host_template uas_host_template = {
	.module = THIS_MODULE,
	.name = "uas",
	.queuecommand = uas_queuecommand,
888
	.target_alloc = uas_target_alloc,
Matthew Wilcox's avatar
Matthew Wilcox committed
889 890 891
	.slave_alloc = uas_slave_alloc,
	.slave_configure = uas_slave_configure,
	.eh_abort_handler = uas_eh_abort_handler,
892
	.eh_device_reset_handler = uas_eh_device_reset_handler,
Matthew Wilcox's avatar
Matthew Wilcox committed
893 894 895 896 897
	.this_id = -1,
	.sg_tablesize = SG_NONE,
	.skip_settle_delay = 1,
};

898 899 900 901 902 903
#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
904
static struct usb_device_id uas_usb_ids[] = {
905
#	include "unusual_uas.h"
Matthew Wilcox's avatar
Matthew Wilcox committed
906 907 908 909 910 911
	{ 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) },
	{ }
};
MODULE_DEVICE_TABLE(usb, uas_usb_ids);

912 913
#undef UNUSUAL_DEV

914 915 916
static int uas_switch_interface(struct usb_device *udev,
				struct usb_interface *intf)
{
917
	struct usb_host_interface *alt;
918 919

	alt = uas_find_uas_alt_setting(intf);
920 921
	if (!alt)
		return -ENODEV;
922

923 924
	return usb_set_interface(udev, alt->desc.bInterfaceNumber,
			alt->desc.bAlternateSetting);
925 926
}

927
static int uas_configure_endpoints(struct uas_dev_info *devinfo)
928 929 930 931 932 933
{
	struct usb_host_endpoint *eps[4] = { };
	struct usb_device *udev = devinfo->udev;
	int r;

	r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
934 935 936 937 938 939 940 941 942 943 944
	if (r)
		return r;

	devinfo->cmd_pipe = usb_sndbulkpipe(udev,
					    usb_endpoint_num(&eps[0]->desc));
	devinfo->status_pipe = usb_rcvbulkpipe(udev,
					    usb_endpoint_num(&eps[1]->desc));
	devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
					    usb_endpoint_num(&eps[2]->desc));
	devinfo->data_out_pipe = usb_sndbulkpipe(udev,
					    usb_endpoint_num(&eps[3]->desc));
Matthew Wilcox's avatar
Matthew Wilcox committed
945

946
	if (udev->speed < USB_SPEED_SUPER) {
947
		devinfo->qdepth = 32;
Matthew Wilcox's avatar
Matthew Wilcox committed
948 949
		devinfo->use_streams = 0;
	} else {
950
		devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
951
						    3, MAX_CMNDS, GFP_NOIO);
952 953
		if (devinfo->qdepth < 0)
			return devinfo->qdepth;
Matthew Wilcox's avatar
Matthew Wilcox committed
954 955
		devinfo->use_streams = 1;
	}
956 957

	return 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
958 959
}

960 961 962 963 964 965 966 967
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);
968
	usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO);
969 970
}

Matthew Wilcox's avatar
Matthew Wilcox committed
971 972
static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
973 974
	int result = -ENOMEM;
	struct Scsi_Host *shost = NULL;
Matthew Wilcox's avatar
Matthew Wilcox committed
975 976
	struct uas_dev_info *devinfo;
	struct usb_device *udev = interface_to_usbdev(intf);
977
	unsigned long dev_flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
978

979
	if (!uas_use_uas_driver(intf, id, &dev_flags))
980 981
		return -ENODEV;

982 983
	if (uas_switch_interface(udev, intf))
		return -ENODEV;
Matthew Wilcox's avatar
Matthew Wilcox committed
984

Hans de Goede's avatar
Hans de Goede committed
985 986
	shost = scsi_host_alloc(&uas_host_template,
				sizeof(struct uas_dev_info));
Matthew Wilcox's avatar
Matthew Wilcox committed
987
	if (!shost)
988
		goto set_alt0;
Matthew Wilcox's avatar
Matthew Wilcox committed
989 990 991

	shost->max_cmd_len = 16 + 252;
	shost->max_id = 1;
992 993
	shost->max_lun = 256;
	shost->max_channel = 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
994 995
	shost->sg_tablesize = udev->bus->sg_tablesize;

Hans de Goede's avatar
Hans de Goede committed
996
	devinfo = (struct uas_dev_info *)shost->hostdata;
Matthew Wilcox's avatar
Matthew Wilcox committed
997 998
	devinfo->intf = intf;
	devinfo->udev = udev;
999
	devinfo->resetting = 0;
Hans de Goede's avatar
Hans de Goede committed
1000
	devinfo->shutdown = 0;
1001
	devinfo->flags = dev_flags;
1002
	init_usb_anchor(&devinfo->cmd_urbs);
1003 1004
	init_usb_anchor(&devinfo->sense_urbs);
	init_usb_anchor(&devinfo->data_urbs);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
1005
	spin_lock_init(&devinfo->lock);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
1006
	INIT_WORK(&devinfo->work, uas_do_work);
EJ Hsu's avatar
EJ Hsu committed
1007
	INIT_WORK(&devinfo->scan_work, uas_scan_work);
1008 1009 1010 1011

	result = uas_configure_endpoints(devinfo);
	if (result)
		goto set_alt0;
Matthew Wilcox's avatar
Matthew Wilcox committed
1012

1013 1014 1015 1016 1017 1018
	/*
	 * 1 tag is reserved for untagged commands +
	 * 1 tag to avoid off by one errors in some bridge firmwares
	 */
	shost->can_queue = devinfo->qdepth - 2;

1019
	usb_set_intfdata(intf, shost);
1020 1021
	result = scsi_add_host(shost, &intf->dev);
	if (result)
1022
		goto free_streams;
1023

EJ Hsu's avatar
EJ Hsu committed
1024 1025 1026
	/* Submit the delayed_work for SCSI-device scanning */
	schedule_work(&devinfo->scan_work);

Matthew Wilcox's avatar
Matthew Wilcox committed
1027
	return result;
1028

1029
free_streams:
1030
	uas_free_streams(devinfo);
1031
	usb_set_intfdata(intf, NULL);
1032 1033
set_alt0:
	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
Matthew Wilcox's avatar
Matthew Wilcox committed
1034 1035 1036 1037 1038
	if (shost)
		scsi_host_put(shost);
	return result;
}

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
static int uas_cmnd_list_empty(struct uas_dev_info *devinfo)
{
	unsigned long flags;
	int i, r = 1;

	spin_lock_irqsave(&devinfo->lock, flags);

	for (i = 0; i < devinfo->qdepth; i++) {
		if (devinfo->cmnd[i]) {
			r = 0; /* Not empty */
			break;
		}
	}

	spin_unlock_irqrestore(&devinfo->lock, flags);

	return r;
}

/*
 * Wait for any pending cmnds to complete, on usb-2 sense_urbs may temporarily
 * get empty while there still is more work to do due to sense-urbs completing
 * with a READ/WRITE_READY iu code, so keep waiting until the list gets empty.
 */
static int uas_wait_for_pending_cmnds(struct uas_dev_info *devinfo)
{
	unsigned long start_time;
	int r;

	start_time = jiffies;
	do {
		flush_work(&devinfo->work);

		r = usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000);
		if (r == 0)
			return -ETIME;

		r = usb_wait_anchor_empty_timeout(&devinfo->data_urbs, 500);
		if (r == 0)
			return -ETIME;

		if (time_after(jiffies, start_time + 5 * HZ))
			return -ETIME;
	} while (!uas_cmnd_list_empty(devinfo));

	return 0;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
1087 1088
static int uas_pre_reset(struct usb_interface *intf)
{
1089
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1090
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
1091 1092
	unsigned long flags;

Hans de Goede's avatar
Hans de Goede committed
1093 1094 1095
	if (devinfo->shutdown)
		return 0;

1096 1097 1098 1099 1100
	/* Block new requests */
	spin_lock_irqsave(shost->host_lock, flags);
	scsi_block_requests(shost);
	spin_unlock_irqrestore(shost->host_lock, flags);

1101
	if (uas_wait_for_pending_cmnds(devinfo) != 0) {
1102
		shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
1103
		scsi_unblock_requests(shost);
1104 1105 1106 1107 1108
		return 1;
	}

	uas_free_streams(devinfo);

Matthew Wilcox's avatar
Matthew Wilcox committed
1109 1110 1111 1112 1113
	return 0;
}

static int uas_post_reset(struct usb_interface *intf)
{
1114
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1115
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
1116
	unsigned long flags;
1117
	int err;
1118

Hans de Goede's avatar
Hans de Goede committed
1119 1120 1121
	if (devinfo->shutdown)
		return 0;

1122
	err = uas_configure_endpoints(devinfo);
1123
	if (err && err != -ENODEV)
1124
		shost_printk(KERN_ERR, shost,
1125 1126
			     "%s: alloc streams error %d after reset",
			     __func__, err);
1127

1128
	/* we must unblock the host in every case lest we deadlock */
1129 1130 1131 1132 1133 1134
	spin_lock_irqsave(shost->host_lock, flags);
	scsi_report_bus_reset(shost, 0);
	spin_unlock_irqrestore(shost->host_lock, flags);

	scsi_unblock_requests(shost);

1135
	return err ? 1 : 0;
Matthew Wilcox's avatar
Matthew Wilcox committed
1136 1137
}

1138 1139 1140
static int uas_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1141
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
1142

1143
	if (uas_wait_for_pending_cmnds(devinfo) != 0) {
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
		shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
		return -ETIME;
	}

	return 0;
}

static int uas_resume(struct usb_interface *intf)
{
	return 0;
}

static int uas_reset_resume(struct usb_interface *intf)
{
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1159
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
1160
	unsigned long flags;
1161
	int err;
1162

1163 1164
	err = uas_configure_endpoints(devinfo);
	if (err) {
1165
		shost_printk(KERN_ERR, shost,
1166 1167
			     "%s: alloc streams error %d after reset",
			     __func__, err);
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
		return -EIO;
	}

	spin_lock_irqsave(shost->host_lock, flags);
	scsi_report_bus_reset(shost, 0);
	spin_unlock_irqrestore(shost->host_lock, flags);

	return 0;
}

Matthew Wilcox's avatar
Matthew Wilcox committed
1178 1179 1180
static void uas_disconnect(struct usb_interface *intf)
{
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1181
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
1182
	unsigned long flags;
Matthew Wilcox's avatar
Matthew Wilcox committed
1183

1184
	spin_lock_irqsave(&devinfo->lock, flags);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
1185
	devinfo->resetting = 1;
1186 1187
	spin_unlock_irqrestore(&devinfo->lock, flags);

Gerd Hoffmann's avatar
Gerd Hoffmann committed
1188
	cancel_work_sync(&devinfo->work);
1189
	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
1190 1191
	usb_kill_anchored_urbs(&devinfo->sense_urbs);
	usb_kill_anchored_urbs(&devinfo->data_urbs);
1192 1193
	uas_zap_pending(devinfo, DID_NO_CONNECT);

EJ Hsu's avatar
EJ Hsu committed
1194 1195 1196 1197 1198 1199
	/*
	 * Prevent SCSI scanning (if it hasn't started yet)
	 * or wait for the SCSI-scanning routine to stop.
	 */
	cancel_work_sync(&devinfo->scan_work);

Gerd Hoffmann's avatar
Gerd Hoffmann committed
1200
	scsi_remove_host(shost);
1201
	uas_free_streams(devinfo);
Hans de Goede's avatar
Hans de Goede committed
1202
	scsi_host_put(shost);
Matthew Wilcox's avatar
Matthew Wilcox committed
1203 1204
}

Hans de Goede's avatar
Hans de Goede committed
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214
/*
 * Put the device back in usb-storage mode on shutdown, as some BIOS-es
 * hang on reboot when the device is still in uas mode. Note the reset is
 * necessary as some devices won't revert to usb-storage mode without it.
 */
static void uas_shutdown(struct device *dev)
{
	struct usb_interface *intf = to_usb_interface(dev);
	struct usb_device *udev = interface_to_usbdev(intf);
	struct Scsi_Host *shost = usb_get_intfdata(intf);
Hans de Goede's avatar
Hans de Goede committed
1215
	struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
Hans de Goede's avatar
Hans de Goede committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225

	if (system_state != SYSTEM_RESTART)
		return;

	devinfo->shutdown = 1;
	uas_free_streams(devinfo);
	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
	usb_reset_device(udev);
}

Matthew Wilcox's avatar
Matthew Wilcox committed
1226 1227 1228 1229 1230 1231
static struct usb_driver uas_driver = {
	.name = "uas",
	.probe = uas_probe,
	.disconnect = uas_disconnect,
	.pre_reset = uas_pre_reset,
	.post_reset = uas_post_reset,
1232 1233 1234
	.suspend = uas_suspend,
	.resume = uas_resume,
	.reset_resume = uas_reset_resume,
Hans de Goede's avatar
Hans de Goede committed
1235
	.drvwrap.driver.shutdown = uas_shutdown,
Matthew Wilcox's avatar
Matthew Wilcox committed
1236 1237 1238
	.id_table = uas_usb_ids,
};

1239
module_usb_driver(uas_driver);
Matthew Wilcox's avatar
Matthew Wilcox committed
1240 1241

MODULE_LICENSE("GPL");
1242 1243
MODULE_AUTHOR(
	"Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp");