Skip to content

Commit

Permalink
rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads
Browse files Browse the repository at this point in the history
In commit a7959c1, 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: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Larry Finger authored and John W. Linville committed Jul 12, 2012
1 parent 2a00def commit 3ce4d85
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
14 changes: 11 additions & 3 deletions drivers/net/wireless/rtlwifi/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,19 @@ static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
u8 request;
u16 wvalue;
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;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */

wvalue = (u16)addr;
_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);
}

Expand Down Expand Up @@ -951,6 +955,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
GFP_KERNEL);
if (!rtlpriv->usb_data)
return -ENOMEM;

/* this spin lock must be initialized early */
spin_lock_init(&rtlpriv->locks.usb_lock);

rtlpriv->usb_data_index = 0;
init_completion(&rtlpriv->firmware_loading_complete);
SET_IEEE80211_DEV(hw, &intf->dev);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/rtlwifi/wifi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,7 @@ struct rtl_locks {
spinlock_t rf_ps_lock;
spinlock_t rf_lock;
spinlock_t waitq_lock;
spinlock_t usb_lock;

/*Dual mac*/
spinlock_t cck_and_rw_pagea_lock;
Expand Down

0 comments on commit 3ce4d85

Please sign in to comment.