Commit e9dc51aa authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by John W. Linville

rt2x00: tune multi-registers I/O timeout

We provide timeout value to rt2x00usb_vendor_request_buff() based on
number of registers to process. That value is passed down to
rt2x00usb_vendor_req_buff_lock() and ends in usb_control_msg(). But we
do not read/write all registers in rt2x00usb_vendor_req_buff_lock() at
once. We read/write them in chunks of 64 bytes in the loop, hence passed
timeout value to low level is too big.

Patch removes timeout argument from rt2x00usb_vendor_request_buff() and
use short REGISTER_TIMEOUT in rt2x00usb_vendor_req_buff_lock(). That
timeout value should be fine for 64 bytes and smaller requests. For
EEPROM read we introduced new timeout value equal to 2 seconds.

Patch fixes process uninterruptible sleep stalls for long period, when
USB bus has problem to satisfy a request and we wait very long time on
usb_start_wait_urb().
Reported-and-tested-by: default avatarSakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ab54bc84
...@@ -62,7 +62,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, ...@@ -62,7 +62,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
__le16 reg; __le16 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset, USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT); &reg, sizeof(reg));
*value = le16_to_cpu(reg); *value = le16_to_cpu(reg);
} }
...@@ -83,8 +83,7 @@ static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, ...@@ -83,8 +83,7 @@ static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
{ {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset, USB_VENDOR_REQUEST_IN, offset,
value, length, value, length);
REGISTER_TIMEOUT16(length));
} }
static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
...@@ -94,7 +93,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, ...@@ -94,7 +93,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
__le16 reg = cpu_to_le16(value); __le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset, USB_VENDOR_REQUEST_OUT, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT); &reg, sizeof(reg));
} }
static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
...@@ -113,8 +112,7 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, ...@@ -113,8 +112,7 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
{ {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset, USB_VENDOR_REQUEST_OUT, offset,
value, length, value, length);
REGISTER_TIMEOUT16(length));
} }
static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
......
...@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock); ...@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype, const u8 request, const u8 requesttype,
const u16 offset, void *buffer, const u16 offset, void *buffer,
const u16 buffer_length, const int timeout) const u16 buffer_length)
{ {
int status = 0; int status = 0;
unsigned char *tb; unsigned char *tb;
...@@ -131,7 +131,7 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, ...@@ -131,7 +131,7 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
bsize = min_t(u16, CSR_CACHE_SIZE, len); bsize = min_t(u16, CSR_CACHE_SIZE, len);
status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
requesttype, off, tb, requesttype, off, tb,
bsize, timeout); bsize, REGISTER_TIMEOUT);
tb += bsize; tb += bsize;
len -= bsize; len -= bsize;
......
...@@ -33,27 +33,14 @@ ...@@ -33,27 +33,14 @@
}) })
/* /*
* For USB vendor requests we need to pass a timeout * For USB vendor requests we need to pass a timeout time in ms, for this we
* time in ms, for this we use the REGISTER_TIMEOUT, * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM
* however when loading firmware a higher value is * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE
* required. In that case we use the REGISTER_TIMEOUT_FIRMWARE. * and EEPROM_TIMEOUT.
*/ */
#define REGISTER_TIMEOUT 500 #define REGISTER_TIMEOUT 500
#define REGISTER_TIMEOUT_FIRMWARE 1000 #define REGISTER_TIMEOUT_FIRMWARE 1000
#define EEPROM_TIMEOUT 2000
/**
* REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access
* @__datalen: Data length
*/
#define REGISTER_TIMEOUT16(__datalen) \
( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) )
/**
* REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access
* @__datalen: Data length
*/
#define REGISTER_TIMEOUT32(__datalen) \
( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) )
/* /*
* Cache size * Cache size
...@@ -126,7 +113,6 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, ...@@ -126,7 +113,6 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
* @offset: Register offset to perform action on * @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device * @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer * @buffer_length: Size of &buffer
* @timeout: Operation timeout
* *
* This function will use a previously with kmalloc allocated cache * This function will use a previously with kmalloc allocated cache
* to communicate with the device. The contents of the buffer pointer * to communicate with the device. The contents of the buffer pointer
...@@ -139,7 +125,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, ...@@ -139,7 +125,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype, const u8 request, const u8 requesttype,
const u16 offset, void *buffer, const u16 offset, void *buffer,
const u16 buffer_length, const int timeout); const u16 buffer_length);
/** /**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered) * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
...@@ -197,8 +183,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, ...@@ -197,8 +183,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
{ {
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0, 0, USB_VENDOR_REQUEST_IN, 0, 0,
eeprom, length, eeprom, length, EEPROM_TIMEOUT);
REGISTER_TIMEOUT16(length));
} }
/** /**
...@@ -217,7 +202,7 @@ static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, ...@@ -217,7 +202,7 @@ static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
__le32 reg; __le32 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset, USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT); &reg, sizeof(reg));
*value = le32_to_cpu(reg); *value = le32_to_cpu(reg);
} }
...@@ -257,8 +242,7 @@ static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, ...@@ -257,8 +242,7 @@ static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
{ {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset, USB_VENDOR_REQUEST_IN, offset,
value, length, value, length);
REGISTER_TIMEOUT32(length));
} }
/** /**
...@@ -277,7 +261,7 @@ static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, ...@@ -277,7 +261,7 @@ static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
__le32 reg = cpu_to_le32(value); __le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset, USB_VENDOR_REQUEST_OUT, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT); &reg, sizeof(reg));
} }
/** /**
...@@ -316,8 +300,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, ...@@ -316,8 +300,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
{ {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset, USB_VENDOR_REQUEST_OUT, offset,
(void *)value, length, (void *)value, length);
REGISTER_TIMEOUT32(length));
} }
/** /**
......
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