diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 199 |
1 files changed, 94 insertions, 105 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 83cc0147f69..3ef318e098e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -74,10 +74,10 @@ static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u32 length) { - int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - value, length, timeout); + value, length, + REGISTER_TIMEOUT32(length)); } static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, @@ -102,10 +102,10 @@ static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u32 length) { - int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - value, length, timeout); + value, length, + REGISTER_TIMEOUT32(length)); } static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) @@ -341,6 +341,17 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev, return 0; } + +static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt73usb_brightness_set; + led->led_dev.blink_set = rt73usb_blink_set; + led->flags = LED_INITIALIZED; +} #endif /* CONFIG_RT73USB_LEDS */ /* @@ -882,7 +893,6 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, char *ptr = data; char *cache; int buflen; - int timeout; /* * Wait for stable hardware. @@ -913,14 +923,14 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) { buflen = min_t(int, len - i, CSR_CACHE_SIZE_FIRMWARE); - timeout = REGISTER_TIMEOUT * (buflen / sizeof(u32)); memcpy(cache, ptr, buflen); rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, FIRMWARE_IMAGE_BASE + i, 0, - cache, buflen, timeout); + cache, buflen, + REGISTER_TIMEOUT32(buflen)); ptr += buflen; } @@ -1091,25 +1101,32 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) +static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) { unsigned int i; - u16 eeprom; - u8 reg_id; u8 value; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) - goto continue_csr_init; - NOTICE(rt2x00dev, "Waiting for BBP register.\n"); + return 0; udelay(REGISTER_BUSY_DELAY); } ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); return -EACCES; +} + +static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; -continue_csr_init: rt73usb_bbp_write(rt2x00dev, 3, 0x80); rt73usb_bbp_write(rt2x00dev, 15, 0x30); rt73usb_bbp_write(rt2x00dev, 21, 0xc8); @@ -1159,7 +1176,8 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + (state == STATE_RADIO_RX_OFF) || + (state == STATE_RADIO_RX_OFF_LINK)); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1168,11 +1186,9 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt73usb_init_registers(rt2x00dev) || - rt73usb_init_bbp(rt2x00dev)) { - ERROR(rt2x00dev, "Register initialization failed.\n"); + if (unlikely(rt73usb_init_registers(rt2x00dev) || + rt73usb_init_bbp(rt2x00dev))) return -EIO; - } return 0; } @@ -1194,7 +1210,6 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) u32 reg; unsigned int i; char put_to_sleep; - char current_state; put_to_sleep = (state != STATE_AWAKE); @@ -1210,16 +1225,12 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); - current_state = - rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); - if (current_state == !put_to_sleep) + state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); + if (state == !put_to_sleep) return 0; msleep(10); } - NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state %d.\n", !put_to_sleep, current_state); - return -EBUSY; } @@ -1237,11 +1248,13 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_RX_ON: case STATE_RADIO_RX_ON_LINK: - rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - break; case STATE_RADIO_RX_OFF: case STATE_RADIO_RX_OFF_LINK: - rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt73usb_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + /* No support, but no error either */ break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1254,6 +1267,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; } + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + return retval; } @@ -1262,8 +1279,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txentry_desc *txdesc, - struct ieee80211_tx_control *control) + struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; @@ -1308,10 +1324,10 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - !!(control->flags & - IEEE80211_TXCTL_LONG_RETRY_LIMIT)); + test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, + skb->len - skbdesc->desc_len); rt2x00_set_field32(&word, TXD_W0_BURST2, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); @@ -1337,12 +1353,14 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const unsigned int queue) + const enum data_queue_qid queue) { u32 reg; - if (queue != RT2X00_BCN_QUEUE_BEACON) + if (queue != QID_BEACON) { + rt2x00usb_kick_tx_queue(rt2x00dev, queue); return; + } /* * For Wi-Fi faily generated beacons between participating stations. @@ -1412,25 +1430,22 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxd = (__le32 *)entry->skb->data; - unsigned int offset = entry->queue->desc_size + 2; u32 word0; u32 word1; /* - * Copy descriptor to the available headroom inside the skbuffer. + * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of + * frame data in rt2x00usb. */ - skb_push(entry->skb, offset); - memcpy(entry->skb->data, rxd, entry->queue->desc_size); - rxd = (__le32 *)entry->skb->data; + memcpy(skbdesc->desc, rxd, skbdesc->desc_len); + rxd = (__le32 *)skbdesc->desc; /* - * The descriptor is now aligned to 4 bytes and thus it is - * now safe to read it on all architectures. + * It is now safe to read the descriptor on all architectures. */ rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; @@ -1444,25 +1459,16 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->dev_flags = 0; if (rt2x00_get_field32(word0, RXD_W0_OFDM)) rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; /* - * Adjust the skb memory window to the frame boundaries. + * Set skb pointers, and update frame information. */ - skb_pull(entry->skb, offset + entry->queue->desc_size); + skb_pull(entry->skb, entry->queue->desc_size); skb_trim(entry->skb, rxdesc->size); - - /* - * Set descriptor and data pointer. - */ - skbdesc->data = entry->skb->data; - skbdesc->data_len = rxdesc->size; - skbdesc->desc = rxd; - skbdesc->desc_len = entry->queue->desc_size; } /* @@ -1635,31 +1641,11 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT73USB_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - rt2x00dev->led_radio.rt2x00dev = rt2x00dev; - rt2x00dev->led_radio.type = LED_TYPE_RADIO; - rt2x00dev->led_radio.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_radio.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_radio.flags = LED_INITIALIZED; - - rt2x00dev->led_assoc.rt2x00dev = rt2x00dev; - rt2x00dev->led_assoc.type = LED_TYPE_ASSOC; - rt2x00dev->led_assoc.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_assoc.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_assoc.flags = LED_INITIALIZED; - - if (value == LED_MODE_SIGNAL_STRENGTH) { - rt2x00dev->led_qual.rt2x00dev = rt2x00dev; - rt2x00dev->led_qual.type = LED_TYPE_QUALITY; - rt2x00dev->led_qual.led_dev.brightness_set = - rt73usb_brightness_set; - rt2x00dev->led_qual.led_dev.blink_set = - rt73usb_blink_set; - rt2x00dev->led_qual.flags = LED_INITIALIZED; - } + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + if (value == LED_MODE_SIGNAL_STRENGTH) + rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual, + LED_TYPE_QUALITY); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, @@ -1837,13 +1823,11 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; - rt2x00dev->hw->max_signal = MAX_SIGNAL; - rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->queues = 4; - SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -1965,20 +1949,28 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) #define rt73usb_get_tsf NULL #endif -static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control) +static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(control->vif); + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct skb_frame_desc *skbdesc; + struct txentry_desc txdesc; unsigned int beacon_base; - unsigned int timeout; u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; /* + * Copy all TX descriptor information into txdesc, + * after that we are free to use the skb->cb array + * for our information. + */ + intf->beacon->skb = skb; + rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); + + /* * Add the descriptor in front of the skb. */ skb_push(skb, intf->beacon->queue->desc_size); @@ -1989,9 +1981,6 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data + intf->beacon->queue->desc_size; - skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; @@ -2007,23 +1996,22 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); /* - * mac80211 doesn't provide the control->queue variable - * for beacons. Set our own queue identification so - * it can be used during descriptor initialization. - */ - control->queue = RT2X00_BCN_QUEUE_BEACON; - rt2x00lib_write_tx_desc(rt2x00dev, skb, control); - - /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ + rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32)); rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, beacon_base, 0, - skb->data, skb->len, timeout); - rt73usb_kick_tx_queue(rt2x00dev, control->queue); + skb->data, skb->len, + REGISTER_TIMEOUT32(skb->len)); + rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); + + /* + * Clean up the beacon skb. + */ + dev_kfree_skb(skb); + intf->beacon->skb = NULL; return 0; } @@ -2074,21 +2062,21 @@ static const struct data_queue_desc rt73usb_queue_rx = { .entry_num = RX_ENTRIES, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb_rx), + .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_tx = { .entry_num = TX_ENTRIES, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb_tx), + .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_bcn = { .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb_tx), + .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct rt2x00_ops rt73usb_ops = { @@ -2097,6 +2085,7 @@ static const struct rt2x00_ops rt73usb_ops = { .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .tx_queues = NUM_TX_QUEUES, .rx = &rt73usb_queue_rx, .tx = &rt73usb_queue_tx, .bcn = &rt73usb_queue_bcn, |