#include <linux/blkdev.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/storage.h>
/* 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);
+static void uas_do_work(struct work_struct *work);
+static DECLARE_WORK(uas_work, uas_do_work);
static DEFINE_SPINLOCK(uas_work_lock);
static LIST_HEAD(uas_work_list);
static void uas_do_work(struct work_struct *work)
{
struct uas_cmd_info *cmdinfo;
+ struct uas_cmd_info *temp;
struct list_head list;
+ int err;
spin_lock_irq(&uas_work_lock);
list_replace_init(&uas_work_list, &list);
spin_unlock_irq(&uas_work_lock);
- list_for_each_entry(cmdinfo, &list, list) {
+ 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);
- uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL);
+ err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+ 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);
+ }
}
}
-static DECLARE_WORK(uas_work, uas_do_work);
-
static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
{
struct sense_iu *sense_iu = urb->transfer_buffer;
goto free;
iu->iu_id = IU_ID_COMMAND;
- iu->tag = cpu_to_be16(stream_id);
- if (sdev->ordered_tags && (cmnd->request->cmd_flags & REQ_HARDBARRIER))
- iu->prio_attr = UAS_ORDERED_TAG;
+ if (blk_rq_tagged(cmnd->request))
+ iu->tag = cpu_to_be16(cmnd->request->tag + 1);
else
- iu->prio_attr = UAS_SIMPLE_TAG;
+ iu->tag = cpu_to_be16(1);
+ iu->prio_attr = UAS_SIMPLE_TAG;
iu->len = len;
int_to_scsilun(sdev->lun, &iu->lun);
memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
return 0;
}
-static int uas_queuecommand(struct scsi_cmnd *cmnd,
+static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
void (*done)(struct scsi_cmnd *))
{
struct scsi_device *sdev = cmnd->device;
return 0;
}
+static DEF_SCSI_QCMD(uas_queuecommand)
+
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
{
struct scsi_device *sdev = cmnd->device;