Skip to content

Commit ab4b716

Browse files
bmorkgregkh
authored andcommitted
USB: storage: fix Huawei mode switching regression
This reverts commit 200e0d9 ("USB: storage: optimize to match the Huawei USB storage devices and support new switch command" and the followup bugfix commit cd06095 ("USB: storage: properly handle the endian issues of idProduct"). The commit effectively added a large number of Huawei devices to the deprecated usb-storage mode switching logic. Many of these devices have been in use and supported by the userspace usb_modeswitch utility for years. Forcing the switching inside the kernel causes a number of regressions as a result of ignoring existing onfigurations, and also completely takes away the ability to configure mode switching per device/system/user. Known regressions caused by this: - Some of the devices support multiple modes, using different switching commands. There are existing configurations taking advantage of this. - There is a real use case for disabling mode switching and instead mounting the exposed storage device. This becomes impossible with switching logic inside the usb-storage driver. - At least on device fail as a result of the usb-storage switching command, becoming completely unswitchable. This is possibly a firmware bug, but still a regression because the device work as expected using usb_modeswitch defaults. In-kernel mode switching was deprecated years ago with the development of the more user friendly userspace alternatives. The existing list of devices in usb-storage was only kept to prevent breaking already working systems. The long term plan is to remove the list, not to add to it. Ref: http://permalink.gmane.org/gmane.linux.usb.general/28543 Cc: <fangxiaozhi@huawei.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent fbb8c74 commit ab4b716

File tree

3 files changed

+331
-78
lines changed

3 files changed

+331
-78
lines changed

drivers/usb/storage/initializers.c

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
9292
return 0;
9393
}
9494

95-
/* This places the HUAWEI usb dongles in multi-port mode */
96-
static int usb_stor_huawei_feature_init(struct us_data *us)
95+
/* This places the HUAWEI E220 devices in multi-port mode */
96+
int usb_stor_huawei_e220_init(struct us_data *us)
9797
{
9898
int result;
9999

@@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us)
104104
US_DEBUGP("Huawei mode set result is %d\n", result);
105105
return 0;
106106
}
107-
108-
/*
109-
* It will send a scsi switch command called rewind' to huawei dongle.
110-
* When the dongle receives this command at the first time,
111-
* it will reboot immediately. After rebooted, it will ignore this command.
112-
* So it is unnecessary to read its response.
113-
*/
114-
static int usb_stor_huawei_scsi_init(struct us_data *us)
115-
{
116-
int result = 0;
117-
int act_len = 0;
118-
struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
119-
char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
120-
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
121-
122-
bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
123-
bcbw->Tag = 0;
124-
bcbw->DataTransferLength = 0;
125-
bcbw->Flags = bcbw->Lun = 0;
126-
bcbw->Length = sizeof(rewind_cmd);
127-
memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
128-
memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
129-
130-
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
131-
US_BULK_CB_WRAP_LEN, &act_len);
132-
US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
133-
return result;
134-
}
135-
136-
/*
137-
* It tries to find the supported Huawei USB dongles.
138-
* In Huawei, they assign the following product IDs
139-
* for all of their mobile broadband dongles,
140-
* including the new dongles in the future.
141-
* So if the product ID is not included in this list,
142-
* it means it is not Huawei's mobile broadband dongles.
143-
*/
144-
static int usb_stor_huawei_dongles_pid(struct us_data *us)
145-
{
146-
struct usb_interface_descriptor *idesc;
147-
int idProduct;
148-
149-
idesc = &us->pusb_intf->cur_altsetting->desc;
150-
idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
151-
/* The first port is CDROM,
152-
* means the dongle in the single port mode,
153-
* and a switch command is required to be sent. */
154-
if (idesc && idesc->bInterfaceNumber == 0) {
155-
if ((idProduct == 0x1001)
156-
|| (idProduct == 0x1003)
157-
|| (idProduct == 0x1004)
158-
|| (idProduct >= 0x1401 && idProduct <= 0x1500)
159-
|| (idProduct >= 0x1505 && idProduct <= 0x1600)
160-
|| (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
161-
return 1;
162-
}
163-
}
164-
return 0;
165-
}
166-
167-
int usb_stor_huawei_init(struct us_data *us)
168-
{
169-
int result = 0;
170-
171-
if (usb_stor_huawei_dongles_pid(us)) {
172-
if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446)
173-
result = usb_stor_huawei_scsi_init(us);
174-
else
175-
result = usb_stor_huawei_feature_init(us);
176-
}
177-
return result;
178-
}

drivers/usb/storage/initializers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
4646
* flash reader */
4747
int usb_stor_ucr61s2b_init(struct us_data *us);
4848

49-
/* This places the HUAWEI usb dongles in multi-port mode */
50-
int usb_stor_huawei_init(struct us_data *us);
49+
/* This places the HUAWEI E220 devices in multi-port mode */
50+
int usb_stor_huawei_e220_init(struct us_data *us);

0 commit comments

Comments
 (0)