aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2006-01-05 03:26:30 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-31 20:23:36 -0500
commit2c2e4a2e07f4c16486dd2ac859eb9c558b1c9935 (patch)
treec336fc942fbcc203d3f302f4c82896d409d25085
parentb31f821c6dee6f3ecfca6b2583a6552538fb91bf (diff)
[PATCH] USB: ub 05 Bulk reset
For crying out loud, they have devices which do not like port resets. So, do what usb-storage does and try both bulk and port resets. We start with a port reset (which usb-storage does at the end of transport), then do a Bulk reset, then a port reset again. This seems to work for me. The code is getting dirtier and dirtier here, but I swear that I'll do something about it (see those two new XXX). Honest. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/block/ub.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c3600cb36365..f04d864770ad 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -14,7 +14,6 @@
14 * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries 14 * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
15 * -- verify the 13 conditions and do bulk resets 15 * -- verify the 13 conditions and do bulk resets
16 * -- kill last_pipe and simply do two-state clearing on both pipes 16 * -- kill last_pipe and simply do two-state clearing on both pipes
17 * -- verify protocol (bulk) from USB descriptors (maybe...)
18 * -- highmem 17 * -- highmem
19 * -- move top_sense and work_bcs into separate allocations (if they survive) 18 * -- move top_sense and work_bcs into separate allocations (if they survive)
20 * for cache purists and esoteric architectures. 19 * for cache purists and esoteric architectures.
@@ -420,11 +419,13 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
420static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, 419static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
421 int stalled_pipe); 420 int stalled_pipe);
422static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); 421static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
423static void ub_reset_enter(struct ub_dev *sc); 422static void ub_reset_enter(struct ub_dev *sc, int try);
424static void ub_reset_task(void *arg); 423static void ub_reset_task(void *arg);
425static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); 424static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
426static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, 425static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
427 struct ub_capacity *ret); 426 struct ub_capacity *ret);
427static int ub_sync_reset(struct ub_dev *sc);
428static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe);
428static int ub_probe_lun(struct ub_dev *sc, int lnum); 429static int ub_probe_lun(struct ub_dev *sc, int lnum);
429 430
430/* 431/*
@@ -983,7 +984,7 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
983 if (atomic_read(&sc->poison)) 984 if (atomic_read(&sc->poison))
984 return -ENXIO; 985 return -ENXIO;
985 986
986 ub_reset_enter(sc); 987 ub_reset_enter(sc, urq->current_try);
987 988
988 if (urq->current_try >= 3) 989 if (urq->current_try >= 3)
989 return -EIO; 990 return -EIO;
@@ -1019,8 +1020,6 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
1019 * No exceptions. 1020 * No exceptions.
1020 * 1021 *
1021 * Host is assumed locked. 1022 * Host is assumed locked.
1022 *
1023 * XXX We only support Bulk for the moment.
1024 */ 1023 */
1025static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd) 1024static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1026{ 1025{
@@ -1703,16 +1702,18 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
1703 1702
1704/* 1703/*
1705 * Reset management 1704 * Reset management
1705 * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
1706 * XXX Make usb_sync_reset asynchronous.
1706 */ 1707 */
1707 1708
1708static void ub_reset_enter(struct ub_dev *sc) 1709static void ub_reset_enter(struct ub_dev *sc, int try)
1709{ 1710{
1710 1711
1711 if (sc->reset) { 1712 if (sc->reset) {
1712 /* This happens often on multi-LUN devices. */ 1713 /* This happens often on multi-LUN devices. */
1713 return; 1714 return;
1714 } 1715 }
1715 sc->reset = 1; 1716 sc->reset = try + 1;
1716 1717
1717#if 0 /* Not needed because the disconnect waits for us. */ 1718#if 0 /* Not needed because the disconnect waits for us. */
1718 unsigned long flags; 1719 unsigned long flags;
@@ -1750,6 +1751,11 @@ static void ub_reset_task(void *arg)
1750 if (atomic_read(&sc->poison)) { 1751 if (atomic_read(&sc->poison)) {
1751 printk(KERN_NOTICE "%s: Not resetting disconnected device\n", 1752 printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
1752 sc->name); /* P3 This floods. Remove soon. XXX */ 1753 sc->name); /* P3 This floods. Remove soon. XXX */
1754 } else if ((sc->reset & 1) == 0) {
1755 ub_sync_reset(sc);
1756 msleep(700); /* usb-storage sleeps 6s (!) */
1757 ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
1758 ub_probe_clear_stall(sc, sc->send_bulk_pipe);
1753 } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { 1759 } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
1754 printk(KERN_NOTICE "%s: Not resetting multi-interface device\n", 1760 printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
1755 sc->name); /* P3 This floods. Remove soon. XXX */ 1761 sc->name); /* P3 This floods. Remove soon. XXX */
@@ -2141,6 +2147,52 @@ static void ub_probe_timeout(unsigned long arg)
2141} 2147}
2142 2148
2143/* 2149/*
2150 * Reset with a Bulk reset.
2151 */
2152static int ub_sync_reset(struct ub_dev *sc)
2153{
2154 int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
2155 struct usb_ctrlrequest *cr;
2156 struct completion compl;
2157 struct timer_list timer;
2158 int rc;
2159
2160 init_completion(&compl);
2161
2162 cr = &sc->work_cr;
2163 cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2164 cr->bRequest = US_BULK_RESET_REQUEST;
2165 cr->wValue = cpu_to_le16(0);
2166 cr->wIndex = cpu_to_le16(ifnum);
2167 cr->wLength = cpu_to_le16(0);
2168
2169 usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
2170 (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
2171 sc->work_urb.actual_length = 0;
2172 sc->work_urb.error_count = 0;
2173 sc->work_urb.status = 0;
2174
2175 if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
2176 printk(KERN_WARNING
2177 "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc);
2178 return rc;
2179 }
2180
2181 init_timer(&timer);
2182 timer.function = ub_probe_timeout;
2183 timer.data = (unsigned long) &compl;
2184 timer.expires = jiffies + UB_CTRL_TIMEOUT;
2185 add_timer(&timer);
2186
2187 wait_for_completion(&compl);
2188
2189 del_timer_sync(&timer);
2190 usb_kill_urb(&sc->work_urb);
2191
2192 return sc->work_urb.status;
2193}
2194
2195/*
2144 * Get number of LUNs by the way of Bulk GetMaxLUN command. 2196 * Get number of LUNs by the way of Bulk GetMaxLUN command.
2145 */ 2197 */
2146static int ub_sync_getmaxlun(struct ub_dev *sc) 2198static int ub_sync_getmaxlun(struct ub_dev *sc)