diff options
-rw-r--r-- | drivers/usb/storage/uas.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1d10d5b8204c..4bbaf6e150e4 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c | |||
@@ -125,29 +125,38 @@ struct uas_cmd_info { | |||
125 | /* I hate forward declarations, but I actually have a loop */ | 125 | /* I hate forward declarations, but I actually have a loop */ |
126 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, | 126 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, |
127 | struct uas_dev_info *devinfo, gfp_t gfp); | 127 | struct uas_dev_info *devinfo, gfp_t gfp); |
128 | static void uas_do_work(struct work_struct *work); | ||
128 | 129 | ||
130 | static DECLARE_WORK(uas_work, uas_do_work); | ||
129 | static DEFINE_SPINLOCK(uas_work_lock); | 131 | static DEFINE_SPINLOCK(uas_work_lock); |
130 | static LIST_HEAD(uas_work_list); | 132 | static LIST_HEAD(uas_work_list); |
131 | 133 | ||
132 | static void uas_do_work(struct work_struct *work) | 134 | static void uas_do_work(struct work_struct *work) |
133 | { | 135 | { |
134 | struct uas_cmd_info *cmdinfo; | 136 | struct uas_cmd_info *cmdinfo; |
137 | struct uas_cmd_info *temp; | ||
135 | struct list_head list; | 138 | struct list_head list; |
139 | int err; | ||
136 | 140 | ||
137 | spin_lock_irq(&uas_work_lock); | 141 | spin_lock_irq(&uas_work_lock); |
138 | list_replace_init(&uas_work_list, &list); | 142 | list_replace_init(&uas_work_list, &list); |
139 | spin_unlock_irq(&uas_work_lock); | 143 | spin_unlock_irq(&uas_work_lock); |
140 | 144 | ||
141 | list_for_each_entry(cmdinfo, &list, list) { | 145 | list_for_each_entry_safe(cmdinfo, temp, &list, list) { |
142 | struct scsi_pointer *scp = (void *)cmdinfo; | 146 | struct scsi_pointer *scp = (void *)cmdinfo; |
143 | struct scsi_cmnd *cmnd = container_of(scp, | 147 | struct scsi_cmnd *cmnd = container_of(scp, |
144 | struct scsi_cmnd, SCp); | 148 | struct scsi_cmnd, SCp); |
145 | uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); | 149 | err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); |
150 | if (err) { | ||
151 | list_del(&cmdinfo->list); | ||
152 | spin_lock_irq(&uas_work_lock); | ||
153 | list_add_tail(&cmdinfo->list, &uas_work_list); | ||
154 | spin_unlock_irq(&uas_work_lock); | ||
155 | schedule_work(&uas_work); | ||
156 | } | ||
146 | } | 157 | } |
147 | } | 158 | } |
148 | 159 | ||
149 | static DECLARE_WORK(uas_work, uas_do_work); | ||
150 | |||
151 | static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) | 160 | static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) |
152 | { | 161 | { |
153 | struct sense_iu *sense_iu = urb->transfer_buffer; | 162 | struct sense_iu *sense_iu = urb->transfer_buffer; |