aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00usb.c
diff options
context:
space:
mode:
authorAdam Baker <linux@baker-net.org.uk>2007-10-27 07:43:29 -0400
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:03:03 -0500
commit3d82346c5d0ff0a413c387c6edaadc0ca29a0971 (patch)
tree790b3fcc6ccee693d9ac343626d1296c736a7851 /drivers/net/wireless/rt2x00/rt2x00usb.c
parent4bd7c452a468af30bb3c4d9c3adcdaf3f3c6048c (diff)
rt2x00: Place mutex around USB register access
There is a buffer, csr_cache which is used to hold copies of data being passed to the USB stack which can get corrupted if multiple threads attempt to access CSR registers simultaneously. There is also the possibility if multiple threads try to access BBP or RF registers for the multiple USB operations needed to get interleaved leading to incorrect results. This patch introduces a mutex to prevent such simultaneous access. The interleaved access problem may also affect the PCI devices but if so that will be handled in a follow-up patch. Signed-off-by: Adam Baker <linux@baker-net.org.uk> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index ab97b0600ec8..a8f0f80ddd21 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -31,6 +31,7 @@
31#include <linux/kernel.h> 31#include <linux/kernel.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/usb.h> 33#include <linux/usb.h>
34#include <linux/bug.h>
34 35
35#include "rt2x00.h" 36#include "rt2x00.h"
36#include "rt2x00usb.h" 37#include "rt2x00usb.h"
@@ -52,6 +53,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
52 (requesttype == USB_VENDOR_REQUEST_IN) ? 53 (requesttype == USB_VENDOR_REQUEST_IN) ?
53 usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); 54 usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
54 55
56
55 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 57 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
56 status = usb_control_msg(usb_dev, pipe, request, requesttype, 58 status = usb_control_msg(usb_dev, pipe, request, requesttype,
57 value, offset, buffer, buffer_length, 59 value, offset, buffer, buffer_length,
@@ -76,13 +78,15 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
76} 78}
77EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); 79EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
78 80
79int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, 81int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
80 const u8 request, const u8 requesttype, 82 const u8 request, const u8 requesttype,
81 const u16 offset, void *buffer, 83 const u16 offset, void *buffer,
82 const u16 buffer_length, const int timeout) 84 const u16 buffer_length, const int timeout)
83{ 85{
84 int status; 86 int status;
85 87
88 BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex));
89
86 /* 90 /*
87 * Check for Cache availability. 91 * Check for Cache availability.
88 */ 92 */
@@ -103,6 +107,25 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
103 107
104 return status; 108 return status;
105} 109}
110EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
111
112int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
113 const u8 request, const u8 requesttype,
114 const u16 offset, void *buffer,
115 const u16 buffer_length, const int timeout)
116{
117 int status;
118
119 mutex_lock(&rt2x00dev->usb_cache_mutex);
120
121 status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
122 requesttype, offset, buffer,
123 buffer_length, timeout);
124
125 mutex_unlock(&rt2x00dev->usb_cache_mutex);
126
127 return status;
128}
106EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); 129EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
107 130
108/* 131/*
@@ -507,6 +530,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
507 rt2x00dev->dev = usb_intf; 530 rt2x00dev->dev = usb_intf;
508 rt2x00dev->ops = ops; 531 rt2x00dev->ops = ops;
509 rt2x00dev->hw = hw; 532 rt2x00dev->hw = hw;
533 mutex_init(&rt2x00dev->usb_cache_mutex);
510 534
511 rt2x00dev->usb_maxpacket = 535 rt2x00dev->usb_maxpacket =
512 usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); 536 usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);