Commit 4fc6a970 authored by Larry Finger's avatar Larry Finger Committed by Ben Hutchings

rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads

commit 3ce4d85b upstream.

In commit a7959c13, the USB part of rtlwifi was switched to convert
_usb_read_sync() to using a preallocated buffer rather than one
that has been acquired using kmalloc. Although this routine is named
as though it were synchronous, there seem to be simultaneous users,
and the selection of the index to the data buffer is not multi-user
safe. This situation is addressed by adding a new spinlock. The routine
cannot sleep, thus a mutex is not allowed.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 5d04d60b
...@@ -120,15 +120,19 @@ static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) ...@@ -120,15 +120,19 @@ static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
u8 request; u8 request;
u16 wvalue; u16 wvalue;
u16 index; u16 index;
__le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; __le32 *data;
unsigned long flags;
spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags);
if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
rtlpriv->usb_data_index = 0;
data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags);
request = REALTEK_USB_VENQT_CMD_REQ; request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)addr; wvalue = (u16)addr;
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
rtlpriv->usb_data_index = 0;
return le32_to_cpu(*data); return le32_to_cpu(*data);
} }
...@@ -909,6 +913,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, ...@@ -909,6 +913,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
GFP_KERNEL); GFP_KERNEL);
if (!rtlpriv->usb_data) if (!rtlpriv->usb_data)
return -ENOMEM; return -ENOMEM;
/* this spin lock must be initialized early */
spin_lock_init(&rtlpriv->locks.usb_lock);
rtlpriv->usb_data_index = 0; rtlpriv->usb_data_index = 0;
SET_IEEE80211_DEV(hw, &intf->dev); SET_IEEE80211_DEV(hw, &intf->dev);
udev = interface_to_usbdev(intf); udev = interface_to_usbdev(intf);
......
...@@ -1550,6 +1550,7 @@ struct rtl_locks { ...@@ -1550,6 +1550,7 @@ struct rtl_locks {
spinlock_t rf_lock; spinlock_t rf_lock;
spinlock_t lps_lock; spinlock_t lps_lock;
spinlock_t waitq_lock; spinlock_t waitq_lock;
spinlock_t usb_lock;
/*Dual mac*/ /*Dual mac*/
spinlock_t cck_and_rw_pagea_lock; spinlock_t cck_and_rw_pagea_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment