Skip to content

Commit 032eaee

Browse files
tanstafelgregkh
authored andcommitted
carl9170: fix sending URBs with wrong type when using full-speed
commit 671796d upstream. The driver assumes that endpoint 4 is always an interrupt endpoint. Unfortunately the type differs between high-speed and full-speed configurations while in the former case it is indeed an interrupt endpoint this is not true for the latter case - here it is a bulk endpoint. When sending URBs with the wrong type the kernel will generate a warning message including backtrace. In this specific case there will be a huge amount of warnings which can bring the system to freeze. To fix this we are now sending URBs to endpoint 4 using the type found in the endpoint descriptor. A side note: The carl9170 firmware currently specifies endpoint 4 as interrupt endpoint even in the full-speed configuration but this has no relevance because before this firmware is loaded the endpoint type is as described above and after the firmware is running the stick is not reenumerated and so the old descriptor is used. Signed-off-by: Ronald Wahl <[email protected]> Signed-off-by: John W. Linville <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent af92ba8 commit 032eaee

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

drivers/net/wireless/ath/carl9170/carl9170.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ struct ar9170 {
256256
atomic_t rx_work_urbs;
257257
atomic_t rx_pool_urbs;
258258
kernel_ulong_t features;
259+
bool usb_ep_cmd_is_bulk;
259260

260261
/* firmware settings */
261262
struct completion fw_load_wait;

drivers/net/wireless/ath/carl9170/usb.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
621621
goto err_free;
622622
}
623623

624-
usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
625-
AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
626-
carl9170_usb_cmd_complete, ar, 1);
624+
if (ar->usb_ep_cmd_is_bulk)
625+
usb_fill_bulk_urb(urb, ar->udev,
626+
usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD),
627+
cmd, cmd->hdr.len + 4,
628+
carl9170_usb_cmd_complete, ar);
629+
else
630+
usb_fill_int_urb(urb, ar->udev,
631+
usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD),
632+
cmd, cmd->hdr.len + 4,
633+
carl9170_usb_cmd_complete, ar, 1);
627634

628635
if (free_buf)
629636
urb->transfer_flags |= URB_FREE_BUFFER;
@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw,
10321039
static int carl9170_usb_probe(struct usb_interface *intf,
10331040
const struct usb_device_id *id)
10341041
{
1042+
struct usb_endpoint_descriptor *ep;
10351043
struct ar9170 *ar;
10361044
struct usb_device *udev;
1037-
int err;
1045+
int i, err;
10381046

10391047
err = usb_reset_device(interface_to_usbdev(intf));
10401048
if (err)
@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf,
10501058
ar->intf = intf;
10511059
ar->features = id->driver_info;
10521060

1061+
/* We need to remember the type of endpoint 4 because it differs
1062+
* between high- and full-speed configuration. The high-speed
1063+
* configuration specifies it as interrupt and the full-speed
1064+
* configuration as bulk endpoint. This information is required
1065+
* later when sending urbs to that endpoint.
1066+
*/
1067+
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) {
1068+
ep = &intf->cur_altsetting->endpoint[i].desc;
1069+
1070+
if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD &&
1071+
usb_endpoint_dir_out(ep) &&
1072+
usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK)
1073+
ar->usb_ep_cmd_is_bulk = true;
1074+
}
1075+
10531076
usb_set_intfdata(intf, ar);
10541077
SET_IEEE80211_DEV(ar->hw, &intf->dev);
10551078

0 commit comments

Comments
 (0)