From c9c3b1a5deac4297503145840fffcd122b253db5 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 10 Nov 2008 19:41:40 +0100 Subject: rt2x00: Cleanup indirect register access All code which accessed indirect registers was similar in respect to the for-loop, the given timeout, etc. Move it into a seperate function, which for PCI drivers can be moved into rt2x00pci. This allows us to cleanup the cleanup the code further by removing the goto statementsand making the codepath look a bit nicer. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 125 +++++++++---------------- drivers/net/wireless/rt2x00/rt2500pci.c | 125 +++++++++---------------- drivers/net/wireless/rt2x00/rt2500usb.c | 140 ++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00pci.c | 25 +++++ drivers/net/wireless/rt2x00/rt2x00pci.h | 18 ++++ drivers/net/wireless/rt2x00/rt61pci.c | 161 ++++++++++++-------------------- drivers/net/wireless/rt2x00/rt73usb.c | 147 +++++++++++++---------------- 7 files changed, 310 insertions(+), 431 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 78fca1bcc54..6a977679124 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -49,20 +49,10 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, BBPCSR, ®); - if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) - break; - udelay(REGISTER_BUSY_DELAY); - } - - return reg; -} +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) @@ -72,31 +62,20 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = rt2400pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; - - /* - * Write the data into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - mutex_unlock(&rt2x00dev->csr_mutex); - - return; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBPCSR_VALUE, value); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); + rt2x00_set_field32(®, BBPCSR_BUSY, 1); + rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); + + rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); } static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -107,74 +86,54 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = rt2400pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBPCSR_REGNUM, word); + rt2x00_set_field32(®, BBPCSR_BUSY, 1); + rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); - /* - * Write the request into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); + rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt2400pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; + WAIT_FOR_BBP(rt2x00dev, ®); + } *value = rt2x00_get_field32(reg, BBPCSR_VALUE); mutex_unlock(&rt2x00dev->csr_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); - *value = 0xff; } static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; - unsigned int i; if (!word) return; mutex_lock(&rt2x00dev->csr_mutex); - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, RFCSR, ®); - if (!rt2x00_get_field32(reg, RFCSR_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RFCSR_VALUE, value); + rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); + rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); + rt2x00_set_field32(®, RFCSR_BUSY, 1); + + rt2x00pci_register_write(rt2x00dev, RFCSR, reg); + rt2x00_rf_write(rt2x00dev, word, value); } - mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field32(®, RFCSR_VALUE, value); - rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); - rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); - rt2x00_set_field32(®, RFCSR_BUSY, 1); - - rt2x00pci_register_write(rt2x00dev, RFCSR, reg); - rt2x00_rf_write(rt2x00dev, word, value); - mutex_unlock(&rt2x00dev->csr_mutex); } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 972b5a5c386..d3bc218ec85 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -49,20 +49,10 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, BBPCSR, ®); - if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) - break; - udelay(REGISTER_BUSY_DELAY); - } - - return reg; -} +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) @@ -72,31 +62,20 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = rt2500pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; - - /* - * Write the data into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - mutex_unlock(&rt2x00dev->csr_mutex); - - return; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBPCSR_VALUE, value); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); + rt2x00_set_field32(®, BBPCSR_BUSY, 1); + rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); + + rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); } static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -107,74 +86,54 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = rt2500pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBPCSR_REGNUM, word); + rt2x00_set_field32(®, BBPCSR_BUSY, 1); + rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); - /* - * Write the request into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); + rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt2500pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, BBPCSR_BUSY)) - goto exit_fail; + WAIT_FOR_BBP(rt2x00dev, ®); + } *value = rt2x00_get_field32(reg, BBPCSR_VALUE); mutex_unlock(&rt2x00dev->csr_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); - *value = 0xff; } static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; - unsigned int i; if (!word) return; mutex_lock(&rt2x00dev->csr_mutex); - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, RFCSR, ®); - if (!rt2x00_get_field32(reg, RFCSR_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RFCSR_VALUE, value); + rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); + rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); + rt2x00_set_field32(®, RFCSR_BUSY, 1); + + rt2x00pci_register_write(rt2x00dev, RFCSR, reg); + rt2x00_rf_write(rt2x00dev, word, value); } - mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field32(®, RFCSR_VALUE, value); - rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); - rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); - rt2x00_set_field32(®, RFCSR_BUSY, 1); - - rt2x00pci_register_write(rt2x00dev, RFCSR, reg); - rt2x00_rf_write(rt2x00dev, word, value); - mutex_unlock(&rt2x00dev->csr_mutex); } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index e6bae4ae4c4..40eb6435882 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -57,7 +57,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, __le16 reg; rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le16_to_cpu(reg); } @@ -68,7 +68,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, __le16 reg; rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le16_to_cpu(reg); } @@ -89,7 +89,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, __le16 reg = cpu_to_le16(value); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, @@ -99,7 +99,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, __le16 reg = cpu_to_le16(value); rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, @@ -112,21 +112,32 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, REGISTER_TIMEOUT16(length)); } -static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + struct rt2x00_field16 field, + u16 *reg) { - u16 reg; unsigned int i; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®); - if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - break; + rt2500usb_register_read_lock(rt2x00dev, offset, reg); + if (!rt2x00_get_field16(*reg, field)) + return 1; udelay(REGISTER_BUSY_DELAY); } - return reg; + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + *reg = ~0; + + return 0; } +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) + static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { @@ -135,30 +146,19 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; - - /* - * Write the data into the BBP. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_DATA, value); - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); - - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - - mutex_unlock(&rt2x00dev->csr_mutex); + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR7_DATA, value); + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); + rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); - return; + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); } static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -169,77 +169,57 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; - - /* - * Write the request into the BBP. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); + rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) + rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); + } - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); mutex_unlock(&rt2x00dev->csr_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); - *value = 0xff; } static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u16 reg; - unsigned int i; if (!word) return; mutex_lock(&rt2x00dev->csr_mutex); - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); - if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); - } - - mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); - reg = 0; - rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); - rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); - rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); - rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); + reg = 0; + rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); + rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); + rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); + rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); - rt2x00_rf_write(rt2x00dev, word, value); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } mutex_unlock(&rt2x00dev->csr_mutex); } diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index e33bd0f150c..d52b22b82d1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -31,6 +31,31 @@ #include "rt2x00.h" #include "rt2x00pci.h" +/* + * Register access. + */ +int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + const struct rt2x00_field32 field, + u32 *reg) +{ + unsigned int i; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00pci_register_read(rt2x00dev, offset, reg); + if (!rt2x00_get_field32(*reg, field)) + return 1; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + *reg = ~0; + + return 0; +} +EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); + /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 96a2082a353..9c0a4d77bc1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -76,6 +76,24 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, memcpy_toio(rt2x00dev->csr.base + offset, value, length); } +/** + * rt2x00pci_regbusy_read - Read from register with busy check + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @field: Field to check if register is busy + * @reg: Pointer to where register contents should be stored + * + * This function will read the given register, and checks if the + * register is busy. If it is, it will sleep for a couple of + * microseconds before reading the register again. If the register + * is not read after a certain timeout, this function will return + * FALSE. + */ +int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + const struct rt2x00_field32 field, + u32 *reg); + /** * rt2x00pci_write_tx_data - Initialize data for TX operation * @entry: The entry where the frame is located diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 89ac34fbadf..d54443c25fe 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -55,20 +55,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); * the access attempt is considered to have failed, * and we will print an error. */ -static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, PHY_CSR3, ®); - if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - break; - udelay(REGISTER_BUSY_DELAY); - } - - return reg; -} +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) +#define WAIT_FOR_MCU(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) @@ -78,30 +71,20 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. - */ - reg = rt61pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; - - /* - * Write the data into the BBP. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); - mutex_unlock(&rt2x00dev->csr_mutex); + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_VALUE, value); + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); + rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); + rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - return; + rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); } static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -112,72 +95,53 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = rt61pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); + rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); + rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - /* - * Write the request into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); + rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); - rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt61pci_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + WAIT_FOR_BBP(rt2x00dev, ®); + } *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); - mutex_unlock(&rt2x00dev->csr_mutex); - - return; -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); - *value = 0xff; } static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; - unsigned int i; if (!word) return; mutex_lock(&rt2x00dev->csr_mutex); - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®); - if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); - } - - mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field32(®, PHY_CSR4_VALUE, value); - rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21); - rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); - rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR4_VALUE, value); + rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21); + rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); + rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); - rt2x00_rf_write(rt2x00dev, word, value); + rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } mutex_unlock(&rt2x00dev->csr_mutex); } @@ -196,32 +160,25 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); - rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); - - if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) - goto exit_fail; - - rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); - rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); - rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); - rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); - - mutex_unlock(&rt2x00dev->csr_mutex); + /* + * Wait until the MCU becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_MCU(rt2x00dev, ®)) { + rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); - return; + rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); + rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, - "mcu request error. Request 0x%02x failed for token 0x%02x.\n", - command, token); } #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d1a63e0017d..b4ca8488bef 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -63,7 +63,7 @@ static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, __le32 reg; rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u32), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le32_to_cpu(reg); } @@ -73,7 +73,7 @@ static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev, __le32 reg; rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u32), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le32_to_cpu(reg); } @@ -93,7 +93,7 @@ static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, __le32 reg = cpu_to_le32(value); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u32), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, @@ -102,7 +102,7 @@ static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, __le32 reg = cpu_to_le32(value); rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u32), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, @@ -115,21 +115,32 @@ static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, REGISTER_TIMEOUT32(length)); } -static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) +static int rt73usb_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + struct rt2x00_field32 field, + u32 *reg) { - u32 reg; unsigned int i; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®); - if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - break; + rt73usb_register_read_lock(rt2x00dev, offset, reg); + if (!rt2x00_get_field32(*reg, field)) + return 1; udelay(REGISTER_BUSY_DELAY); } - return reg; + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + *reg = ~0; + + return 0; } +#define WAIT_FOR_BBP(__dev, __reg) \ + rt73usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt73usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) + static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { @@ -138,30 +149,20 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; - - /* - * Write the data into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - - rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); - mutex_unlock(&rt2x00dev->csr_mutex); - - return; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_VALUE, value); + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); + rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); + rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); + + rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); + } -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); } static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -172,79 +173,59 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->csr_mutex); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); + rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); + rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - /* - * Write the request into the BBP. - */ - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); + rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); - rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + WAIT_FOR_BBP(rt2x00dev, ®); + } *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); - mutex_unlock(&rt2x00dev->csr_mutex); - - return; -exit_fail: mutex_unlock(&rt2x00dev->csr_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); - *value = 0xff; } static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; - unsigned int i; if (!word) return; mutex_lock(&rt2x00dev->csr_mutex); - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); - if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); - } - - mutex_unlock(&rt2x00dev->csr_mutex); - ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field32(®, PHY_CSR4_VALUE, value); - /* - * RF5225 and RF2527 contain 21 bits per RF register value, - * all others contain 20 bits. + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. */ - rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, - 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527))); - rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); - rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - - rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); - rt2x00_rf_write(rt2x00dev, word, value); + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, PHY_CSR4_VALUE, value); + /* + * RF5225 and RF2527 contain 21 bits per RF register value, + * all others contain 20 bits. + */ + rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, + 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF2527))); + rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); + rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); + + rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } mutex_unlock(&rt2x00dev->csr_mutex); } -- cgit v1.2.3 From 0f829b1d6f499447052f98098e41fd6a091eadd0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 10 Nov 2008 19:42:18 +0100 Subject: rt2x00: Move rt73usb register access wrappers into rt2x00usb rt2500usb and rt73usb have different register word sizes, for that reason the register access wrappers were never moved into rt2x00usb. With rt2800usb on its way, we should favor the 32bit register access and move those wrappers into rt2x00usb. That saves duplicate code, since only rt2500usb will need the special 16bit wrappers. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 22 +++ drivers/net/wireless/rt2x00/rt2x00usb.h | 136 ++++++++++++++ drivers/net/wireless/rt2x00/rt73usb.c | 323 ++++++++++++-------------------- 3 files changed, 280 insertions(+), 201 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index c507b0d9409..2fbf78ff6b1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -154,6 +154,28 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); +int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + struct rt2x00_field32 field, + u32 *reg) +{ + unsigned int i; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read_lock(rt2x00dev, offset, reg); + if (!rt2x00_get_field32(*reg, field)) + return 1; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + *reg = ~0; + + return 0; +} +EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); + /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 4104f0e8fa4..2bd4ac855f5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -231,6 +231,142 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, REGISTER_TIMEOUT16(length)); } +/** + * rt2x00usb_regbusy_read - Read 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Pointer to where register contents should be stored + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_request_buff(). + */ +static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 *value) +{ + __le32 reg; + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(reg), REGISTER_TIMEOUT); + *value = le32_to_cpu(reg); +} + +/** + * rt2x00usb_register_read_lock - Read 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Pointer to where register contents should be stored + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_req_buff_lock(). + */ +static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 *value) +{ + __le32 reg; + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(reg), REGISTER_TIMEOUT); + *value = le32_to_cpu(reg); +} + +/** + * rt2x00usb_register_multiread - Read 32bit register words + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Pointer to where register contents should be stored + * @length: Length of the data + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_request_buff(). + */ +static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + void *value, const u32 length) +{ + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + value, length, + REGISTER_TIMEOUT32(length)); +} + +/** + * rt2x00usb_register_write - Write 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Data which should be written + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_request_buff(). + */ +static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 value) +{ + __le32 reg = cpu_to_le32(value); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(reg), REGISTER_TIMEOUT); +} + +/** + * rt2x00usb_register_write_lock - Write 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Data which should be written + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_req_buff_lock(). + */ +static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 value) +{ + __le32 reg = cpu_to_le32(value); + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(reg), REGISTER_TIMEOUT); +} + +/** + * rt2x00usb_register_multiwrite - Write 32bit register words + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @value: Data which should be written + * @length: Length of the data + * + * This function is a simple wrapper for 32bit register access + * through rt2x00usb_vendor_request_buff(). + */ +static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + void *value, const u32 length) +{ + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + value, length, + REGISTER_TIMEOUT32(length)); +} + +/** + * rt2x00usb_regbusy_read - Read from register with busy check + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @field: Field to check if register is busy + * @reg: Pointer to where register contents should be stored + * + * This function will read the given register, and checks if the + * register is busy. If it is, it will sleep for a couple of + * microseconds before reading the register again. If the register + * is not read after a certain timeout, this function will return + * FALSE. + */ +int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + struct rt2x00_field32 field, + u32 *reg); + /* * Radio handlers */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b4ca8488bef..ee59b4e35cd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); /* * Register access. * All access to the CSR registers will go through the methods - * rt73usb_register_read and rt73usb_register_write. + * rt2x00usb_register_read and rt2x00usb_register_write. * BBP and RF register require indirect register access, * and use the CSR registers BBPCSR and RFCSR to achieve this. * These indirect registers work with busy bits, @@ -57,89 +57,10 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); * and we will print an error. * The _lock versions must be used if you already hold the csr_mutex */ -static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 *value) -{ - __le32 reg; - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le32_to_cpu(reg); -} - -static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 *value) -{ - __le32 reg; - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le32_to_cpu(reg); -} - -static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - value, length, - REGISTER_TIMEOUT32(length)); -} - -static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 value) -{ - __le32 reg = cpu_to_le32(value); - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 value) -{ - __le32 reg = cpu_to_le32(value); - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - value, length, - REGISTER_TIMEOUT32(length)); -} - -static int rt73usb_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - struct rt2x00_field32 field, - u32 *reg) -{ - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read_lock(rt2x00dev, offset, reg); - if (!rt2x00_get_field32(*reg, field)) - return 1; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", offset, *reg); - *reg = ~0; - - return 0; -} - #define WAIT_FOR_BBP(__dev, __reg) \ - rt73usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) + rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) #define WAIT_FOR_RF(__dev, __reg) \ - rt73usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) + rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) @@ -159,7 +80,7 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); + rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); } mutex_unlock(&rt2x00dev->csr_mutex); @@ -186,7 +107,7 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); + rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); WAIT_FOR_BBP(rt2x00dev, ®); } @@ -223,7 +144,7 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); + rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); rt2x00_rf_write(rt2x00dev, word, value); } @@ -234,8 +155,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, static const struct rt2x00debug rt73usb_rt2x00debug = { .owner = THIS_MODULE, .csr = { - .read = rt73usb_register_read, - .write = rt73usb_register_write, + .read = rt2x00usb_register_read, + .write = rt2x00usb_register_write, .flags = RT2X00DEBUGFS_OFFSET, .word_base = CSR_REG_BASE, .word_size = sizeof(u32), @@ -314,10 +235,10 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev, container_of(led_cdev, struct rt2x00_led, led_dev); u32 reg; - rt73usb_register_read(led->rt2x00dev, MAC_CSR14, ®); + rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, ®); rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); - rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg); + rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg); return 0; } @@ -360,7 +281,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, */ mask = (0xf << crypto->bssidx); - rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); reg &= mask; if (reg && reg == mask) @@ -397,16 +318,16 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, field.bit_offset = (3 * key->hw_key_idx); field.bit_mask = 0x7 << field.bit_offset; - rt73usb_register_read(rt2x00dev, SEC_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR1, ®); rt2x00_set_field32(®, field, crypto->cipher); - rt73usb_register_write(rt2x00dev, SEC_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg); } else { field.bit_offset = (3 * (key->hw_key_idx - 8)); field.bit_mask = 0x7 << field.bit_offset; - rt73usb_register_read(rt2x00dev, SEC_CSR5, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR5, ®); rt2x00_set_field32(®, field, crypto->cipher); - rt73usb_register_write(rt2x00dev, SEC_CSR5, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg); } /* @@ -429,12 +350,12 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, */ mask = 1 << key->hw_key_idx; - rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); if (crypto->cmd == SET_KEY) reg |= mask; else if (crypto->cmd == DISABLE_KEY) reg &= ~mask; - rt73usb_register_write(rt2x00dev, SEC_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg); return 0; } @@ -459,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, * When both registers are full, we drop the key, * otherwise we use the first invalid entry. */ - rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); if (reg && reg == ~0) { key->hw_key_idx = 32; - rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); if (reg && reg == ~0) return -ENOSPC; } @@ -490,14 +411,14 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, /* * Send the address and cipher type to the hardware register. * This data fits within the CSR cache size, so we can use - * rt73usb_register_multiwrite() directly. + * rt2x00usb_register_multiwrite() directly. */ memset(&addr_entry, 0, sizeof(addr_entry)); memcpy(&addr_entry, crypto->address, ETH_ALEN); addr_entry.cipher = crypto->cipher; reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); - rt73usb_register_multiwrite(rt2x00dev, reg, + rt2x00usb_register_multiwrite(rt2x00dev, reg, &addr_entry, sizeof(addr_entry)); /* @@ -505,9 +426,9 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, * without this received frames will not be decrypted * by the hardware. */ - rt73usb_register_read(rt2x00dev, SEC_CSR4, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR4, ®); reg |= (1 << crypto->bssidx); - rt73usb_register_write(rt2x00dev, SEC_CSR4, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg); /* * The driver does not support the IV/EIV generation @@ -530,21 +451,21 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, if (key->hw_key_idx < 32) { mask = 1 << key->hw_key_idx; - rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); if (crypto->cmd == SET_KEY) reg |= mask; else if (crypto->cmd == DISABLE_KEY) reg &= ~mask; - rt73usb_register_write(rt2x00dev, SEC_CSR2, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg); } else { mask = 1 << (key->hw_key_idx - 32); - rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); + rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); if (crypto->cmd == SET_KEY) reg |= mask; else if (crypto->cmd == DISABLE_KEY) reg &= ~mask; - rt73usb_register_write(rt2x00dev, SEC_CSR3, reg); + rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg); } return 0; @@ -561,7 +482,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, * and broadcast frames will always be accepted since * there is no filter for it at this time. */ - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, !(filter_flags & FIF_FCSFAIL)); rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, @@ -579,7 +500,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, !(filter_flags & FIF_CONTROL)); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); } static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, @@ -598,16 +519,16 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, * bits which (when set to 0) will invalidate the entire beacon. */ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt73usb_register_write(rt2x00dev, beacon_base, 0); + rt2x00usb_register_write(rt2x00dev, beacon_base, 0); /* * Enable synchronisation. */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); } if (flags & CONFIG_UPDATE_MAC) { @@ -615,7 +536,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); conf->mac[1] = cpu_to_le32(reg); - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, + rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, sizeof(conf->mac)); } @@ -624,7 +545,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); conf->bssid[1] = cpu_to_le32(reg); - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, + rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4, conf->bssid, sizeof(conf->bssid)); } } @@ -634,26 +555,26 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); - rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); - rt73usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); - rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); - rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); - rt73usb_register_read(rt2x00dev, MAC_CSR8, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); - rt73usb_register_write(rt2x00dev, MAC_CSR8, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); } static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, @@ -799,14 +720,14 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); - rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); - rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); if (rt2x00_rf(&rt2x00dev->chip, RF5226) || rt2x00_rf(&rt2x00dev->chip, RF5225)) @@ -896,12 +817,12 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, libconf->conf->long_frame_max_tx_count); rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, libconf->conf->short_frame_max_tx_count); - rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); } static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, @@ -909,18 +830,18 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, libconf->conf->beacon_int * 16); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); } static void rt73usb_config(struct rt2x00_dev *rt2x00dev, @@ -953,13 +874,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, /* * Update FCS error count from register. */ - rt73usb_register_read(rt2x00dev, STA_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); /* * Update False CCA count from register. */ - rt73usb_register_read(rt2x00dev, STA_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } @@ -1119,7 +1040,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, * Wait for stable hardware. */ for (i = 0; i < 100; i++) { - rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); if (reg) break; msleep(1); @@ -1161,13 +1082,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ @@ -1176,12 +1097,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg); /* * CCK TXD BBP registers */ - rt73usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, ®); rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); @@ -1190,77 +1111,77 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg); /* * OFDM TXD BBP registers */ - rt73usb_register_read(rt2x00dev, TXRX_CSR3, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, ®); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR7, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, ®); rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); - rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR8, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, ®); rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); - rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg); - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); - rt73usb_register_read(rt2x00dev, MAC_CSR6, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR6, ®); rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff); - rt73usb_register_write(rt2x00dev, MAC_CSR6, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg); - rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); + rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) return -EBUSY; - rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); /* * Invalidate all Shared Keys (SEC_CSR0), * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) */ - rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); - rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); - rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); + rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); + rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); + rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); reg = 0x000023b0; if (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF2527)) rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); - rt73usb_register_write(rt2x00dev, PHY_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); - rt73usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06); - rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); - rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); + rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06); + rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); + rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); - rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); - rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); /* * Clear all beacons @@ -1268,36 +1189,36 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) * the first byte since that byte contains the VALID and OWNER * bits which (when set to 0) will invalidate the entire beacon. */ - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); /* * We must clear the error counters. * These registers are cleared on read, * so we may pass a useless variable to store the value. */ - rt73usb_register_read(rt2x00dev, STA_CSR0, ®); - rt73usb_register_read(rt2x00dev, STA_CSR1, ®); - rt73usb_register_read(rt2x00dev, STA_CSR2, ®); + rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, STA_CSR2, ®); /* * Reset MAC and BBP registers. */ - rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); - rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); - rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); - rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); - rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); - rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); return 0; } @@ -1375,11 +1296,11 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, (state == STATE_RADIO_RX_OFF) || (state == STATE_RADIO_RX_OFF_LINK)); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); } static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -1396,12 +1317,12 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); + rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); /* * Disable synchronisation. */ - rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0); rt2x00usb_disable_radio(rt2x00dev); } @@ -1414,10 +1335,10 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) put_to_sleep = (state != STATE_AWAKE); - rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); - rt73usb_register_write(rt2x00dev, MAC_CSR12, reg); + rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg); /* * Device is not guaranteed to be in the requested state yet. @@ -1425,7 +1346,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) * device has entered the correct state. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); if (state == !put_to_sleep) return 0; @@ -1565,11 +1486,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry) * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); /* * Write entire beacon with descriptor to register. @@ -1616,14 +1537,14 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, * For Wi-Fi faily generated beacons between participating stations. * Set TBTT phase adaptive adjustment step to 8us (default 16us) */ - rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); } } @@ -1862,7 +1783,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { @@ -2216,33 +2137,33 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, field.bit_offset = queue_idx * 16; field.bit_mask = 0xffff << field.bit_offset; - rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); rt2x00_set_field32(®, field, queue->txop); - rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); + rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); } else if (queue_idx < 4) { field.bit_offset = (queue_idx - 2) * 16; field.bit_mask = 0xffff << field.bit_offset; - rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); + rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); rt2x00_set_field32(®, field, queue->txop); - rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); + rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); } /* Update WMM registers */ field.bit_offset = queue_idx * 4; field.bit_mask = 0xf << field.bit_offset; - rt73usb_register_read(rt2x00dev, AIFSN_CSR, ®); + rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, ®); rt2x00_set_field32(®, field, queue->aifs); - rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg); + rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg); - rt73usb_register_read(rt2x00dev, CWMIN_CSR, ®); + rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, ®); rt2x00_set_field32(®, field, queue->cw_min); - rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg); + rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg); - rt73usb_register_read(rt2x00dev, CWMAX_CSR, ®); + rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, ®); rt2x00_set_field32(®, field, queue->cw_max); - rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg); + rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg); return 0; } @@ -2260,9 +2181,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) u64 tsf; u32 reg; - rt73usb_register_read(rt2x00dev, TXRX_CSR13, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, ®); tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; - rt73usb_register_read(rt2x00dev, TXRX_CSR12, ®); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, ®); tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); return tsf; -- cgit v1.2.3 From 0e3de99846489424c2cba952e0a52c269f01009a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 12 Nov 2008 00:01:37 +0100 Subject: rt2x00: Fix TX failure path The callback function write_tx_data() can only fail when our ENTRY_OWNER_DEVICE_DATA flag on a queue entry failed to determine the entry was not available and it is in fact still owned by the hardware. This means that if that function fails the queue must be stopped in mac80211. When rt2x00queue_get_queue() returns NULL in the TX path, it means mac80211 has passed us an invalid queue, although this should be impossible, it shouldn't hurt if we send mac80211 a signal to stop the queue either. Both issues can simply be resolved by removing their manual failure handler and making them use the failure path provided in rt2x00mac_tx(). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 3 +-- drivers/net/wireless/rt2x00/rt2x00queue.c | 14 ++++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 48636b0dd89..4c039572906 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -132,8 +132,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ERROR(rt2x00dev, "Attempt to send packet over invalid queue %d.\n" "Please file bug report to %s.\n", qid, DRV_PROJECT); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + goto exit_fail; } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d7752dbd202..b8de9d2750e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -386,7 +386,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) u8 rate_idx, rate_flags; if (unlikely(rt2x00queue_full(queue))) - return -EINVAL; + return -ENOBUFS; if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { ERROR(queue->rt2x00dev, @@ -415,7 +415,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) tx_info = IEEE80211_SKB_CB(skb); rate_idx = tx_info->control.rates[0].idx; rate_flags = tx_info->control.rates[0].flags; - skbdesc = get_skb_frame_desc(entry->skb); + skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; skbdesc->tx_rate_idx = rate_idx; @@ -427,20 +427,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) * the frame so we can provide it to the driver seperately. */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && - !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { + !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) rt2x00crypto_tx_remove_iv(skb, iv_len); - } /* * It could be possible that the queue was corrupted and this - * call failed. Just drop the frame, we cannot rollback and pass - * the frame to mac80211 because the skb->cb has now been tainted. + * call failed. Since we always return NETDEV_TX_OK to mac80211, + * this frame will simply be dropped. */ if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - dev_kfree_skb_any(entry->skb); entry->skb = NULL; - return 0; + return -EIO; } if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) -- cgit v1.2.3 From f1ca2167d89d991eed519c789d3902f9682c06b8 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Thu, 13 Nov 2008 23:07:33 +0100 Subject: rt2x00: Detect USB BULK in/out endpoints Instead of hardcoding the used in/out endpoints we should detect them by walking through all available endpoints. rt2800usb will gain the most out of this, because the legacy drivers indicate that there are multiple endpoints available. However this code might benefit at least rt73usb as well for the MIMO queues, and if we are really lucky rt2500usb will benefit because for the TX and PRIO queues. Even if rt2500usb and rt73usb do not get better performance after this patch, the endpoint detection still belongs to rt2x00usb, and it shouldn't hurt to always try to detect the available endpoints. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 11 ++-- drivers/net/wireless/rt2x00/rt2x00.h | 8 +-- drivers/net/wireless/rt2x00/rt2x00queue.h | 22 +++++++- drivers/net/wireless/rt2x00/rt2x00usb.c | 91 ++++++++++++++++++++++++++++--- drivers/net/wireless/rt2x00/rt73usb.c | 7 +-- 5 files changed, 111 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 40eb6435882..0447e93306a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1108,7 +1108,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - int pipe = usb_sndbulkpipe(usb_dev, 1); + int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); int length; u16 reg; @@ -1134,7 +1134,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) * length of the data to usb_fill_bulk_urb. Pass the skb * to the driver to determine what the length should be. */ - length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); + length = rt2x00dev->ops->lib->get_tx_data_len(entry); usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, entry->skb->data, length, rt2500usb_beacondone, @@ -1156,8 +1156,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); } -static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb) +static int rt2500usb_get_tx_data_len(struct queue_entry *entry) { int length; @@ -1165,8 +1164,8 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * The length _must_ be a multiple of 2, * but it must _not_ be a multiple of the USB packet size. */ - length = roundup(skb->len, 2); - length += (2 * !(length % rt2x00dev->usb_maxpacket)); + length = roundup(entry->skb->len, 2); + length += (2 * !(length % entry->queue->usb_maxpacket)); return length; } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fee61bee1e7..780ba736581 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -555,8 +555,7 @@ struct rt2x00lib_ops { struct txentry_desc *txdesc); int (*write_tx_data) (struct queue_entry *entry); void (*write_beacon) (struct queue_entry *entry); - int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb); + int (*get_tx_data_len) (struct queue_entry *entry); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue); @@ -798,11 +797,6 @@ struct rt2x00_dev { */ short lna_gain; - /* - * USB Max frame size (for rt2500usb & rt73usb). - */ - u16 usb_maxpacket; - /* * Current TX power value. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4d3c7246f9a..2e99ab53ec6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -380,6 +380,8 @@ enum queue_index { * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). * @data_size: Maximum data size for the frames in this queue. * @desc_size: Hardware descriptor size for the data in this queue. + * @usb_endpoint: Device endpoint used for communication (USB only) + * @usb_maxpacket: Max packet size for given endpoint (USB only) */ struct data_queue { struct rt2x00_dev *rt2x00dev; @@ -401,6 +403,9 @@ struct data_queue { unsigned short data_size; unsigned short desc_size; + + unsigned short usb_endpoint; + unsigned short usb_maxpacket; }; /** @@ -443,6 +448,19 @@ struct data_queue_desc { #define tx_queue_end(__dev) \ &(__dev)->tx[(__dev)->ops->tx_queues] +/** + * queue_next - Return pointer to next queue in list (HELPER MACRO). + * @__queue: Current queue for which we need the next queue + * + * Using the current queue address we take the address directly + * after the queue to take the next queue. Note that this macro + * should be used carefully since it does not protect against + * moving past the end of the list. (See macros &queue_end and + * &tx_queue_end for determining the end of the queue). + */ +#define queue_next(__queue) \ + &(__queue)[1] + /** * queue_loop - Loop through the queues within a specific range (HELPER MACRO). * @__entry: Pointer where the current queue entry will be stored in. @@ -453,8 +471,8 @@ struct data_queue_desc { */ #define queue_loop(__entry, __start, __end) \ for ((__entry) = (__start); \ - prefetch(&(__entry)[1]), (__entry) != (__end); \ - (__entry) = &(__entry)[1]) + prefetch(queue_next(__entry)), (__entry) != (__end);\ + (__entry) = queue_next(__entry)) /** * queue_for_each - Loop through all queues diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 2fbf78ff6b1..83df312ac56 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -234,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) * length of the data to usb_fill_bulk_urb. Pass the skb * to the driver to determine what the length should be. */ - length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); + length = rt2x00dev->ops->lib->get_tx_data_len(entry); usb_fill_bulk_urb(entry_priv->urb, usb_dev, - usb_sndbulkpipe(usb_dev, 1), + usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); @@ -378,10 +378,11 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) struct usb_device *usb_dev = to_usb_device_intf(entry->queue->rt2x00dev->dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; + int pipe; if (entry->queue->qid == QID_RX) { - usb_fill_bulk_urb(entry_priv->urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 1), + pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); + usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, entry->skb->data, entry->skb->len, rt2x00usb_interrupt_rxdone, entry); @@ -393,6 +394,76 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); +static void rt2x00usb_assign_endpoint(struct data_queue *queue, + struct usb_endpoint_descriptor *ep_desc) +{ + struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev); + int pipe; + + queue->usb_endpoint = usb_endpoint_num(ep_desc); + + if (queue->qid == QID_RX) { + pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint); + queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0); + } else { + pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint); + queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1); + } + + if (!queue->usb_maxpacket) + queue->usb_maxpacket = 1; +} + +static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) +{ + struct usb_interface *intf = to_usb_interface(rt2x00dev->dev); + struct usb_host_interface *intf_desc = intf->cur_altsetting; + struct usb_endpoint_descriptor *ep_desc; + struct data_queue *queue = rt2x00dev->tx; + struct usb_endpoint_descriptor *tx_ep_desc = NULL; + unsigned int i; + + /* + * Walk through all available endpoints to search for "bulk in" + * and "bulk out" endpoints. When we find such endpoints collect + * the information we need from the descriptor and assign it + * to the queue. + */ + for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { + ep_desc = &intf_desc->endpoint[i].desc; + + if (usb_endpoint_is_bulk_in(ep_desc)) { + rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); + } else if (usb_endpoint_is_bulk_out(ep_desc)) { + rt2x00usb_assign_endpoint(queue, ep_desc); + + if (queue != queue_end(rt2x00dev)) + queue = queue_next(queue); + tx_ep_desc = ep_desc; + } + } + + /* + * At least 1 endpoint for RX and 1 endpoint for TX must be available. + */ + if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) { + ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n"); + return -EPIPE; + } + + /* + * It might be possible not all queues have a dedicated endpoint. + * Loop through all TX queues and copy the endpoint information + * which we have gathered from already assigned endpoints. + */ + txall_queue_for_each(rt2x00dev, queue) { + if (!queue->usb_endpoint) + rt2x00usb_assign_endpoint(queue, tx_ep_desc); + } + + return 0; +} + static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) { @@ -463,6 +534,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; int status; + /* + * Find endpoints for each queue + */ + status = rt2x00usb_find_endpoints(rt2x00dev); + if (status) + goto exit; + /* * Allocate DMA */ @@ -554,11 +632,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00dev->ops = ops; rt2x00dev->hw = hw; - rt2x00dev->usb_maxpacket = - usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); - if (!rt2x00dev->usb_maxpacket) - rt2x00dev->usb_maxpacket = 1; - retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ee59b4e35cd..37a782dc808 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1508,8 +1508,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry) entry->skb = NULL; } -static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb) +static int rt73usb_get_tx_data_len(struct queue_entry *entry) { int length; @@ -1517,8 +1516,8 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * The length _must_ be a multiple of 4, * but it must _not_ be a multiple of the USB packet size. */ - length = roundup(skb->len, 4); - length += (4 * !(length % rt2x00dev->usb_maxpacket)); + length = roundup(entry->skb->len, 4); + length += (4 * !(length % entry->queue->usb_maxpacket)); return length; } -- cgit v1.2.3 From d507748ac6de67369e76058a8a921cd22734f40a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 16 Nov 2008 00:08:50 +0100 Subject: rt2x00: Don't switch off LED on initialization When we switch off the LEDS during initialization we kill rt73usb from proper functioning. The immediate result after the first LED command are MCU failures and a complete breakdown of TX/RX. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00leds.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 66c61b1eca5..68f4e0fc35b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -111,12 +111,6 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, led->led_dev.name = name; led->led_dev.brightness = LED_OFF; - /* - * Ensure the LED is off, it might have been enabled - * by the hardware when the device was powered on. - */ - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - retval = led_classdev_register(device, &led->led_dev); if (retval) { ERROR(rt2x00dev, "Failed to register led handler.\n"); -- cgit v1.2.3