diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2006-01-05 03:26:30 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-31 20:23:36 -0500 |
commit | 2c2e4a2e07f4c16486dd2ac859eb9c558b1c9935 (patch) | |
tree | c336fc942fbcc203d3f302f4c82896d409d25085 /drivers/block/ub.c | |
parent | b31f821c6dee6f3ecfca6b2583a6552538fb91bf (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>
Diffstat (limited to 'drivers/block/ub.c')
-rw-r--r-- | drivers/block/ub.c | 66 |
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); | |||
420 | static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, | 419 | static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, |
421 | int stalled_pipe); | 420 | int stalled_pipe); |
422 | static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); | 421 | static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); |
423 | static void ub_reset_enter(struct ub_dev *sc); | 422 | static void ub_reset_enter(struct ub_dev *sc, int try); |
424 | static void ub_reset_task(void *arg); | 423 | static void ub_reset_task(void *arg); |
425 | static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); | 424 | static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); |
426 | static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, | 425 | static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, |
427 | struct ub_capacity *ret); | 426 | struct ub_capacity *ret); |
427 | static int ub_sync_reset(struct ub_dev *sc); | ||
428 | static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe); | ||
428 | static int ub_probe_lun(struct ub_dev *sc, int lnum); | 429 | static 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 | */ |
1025 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | 1024 | static 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 | ||
1708 | static void ub_reset_enter(struct ub_dev *sc) | 1709 | static 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 | */ | ||
2152 | static 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 | */ |
2146 | static int ub_sync_getmaxlun(struct ub_dev *sc) | 2198 | static int ub_sync_getmaxlun(struct ub_dev *sc) |