diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-14 20:40:34 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-14 20:40:34 -0700 |
commit | fc943b12e48f9341bce48c2fadf094cc721aab93 (patch) | |
tree | 8c3244d7f5fae4edbfe0a5103789b0bc5c64f478 /drivers/net/wireless/rt2x00 | |
parent | 72d9794f444734af56ef12833b496326643e2964 (diff) | |
parent | 4c9adafff7d910f142fe44fae37ed12c6b99f20f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 89 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 90 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 154 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 37 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00config.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00firmware.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 103 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 115 |
12 files changed, 321 insertions, 401 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 91cbd9e560bd..4c0538d6099b 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1069,6 +1069,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt2400pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_pci *entry_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + u32 word; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + + /* + * Replace rt2x00lib allocated descriptor with the + * pointer to the _real_ hardware descriptor. + * After that, map the beacon to DMA and update the + * descriptor. + */ + memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry_priv->desc; + + rt2x00queue_map_txskb(rt2x00dev, entry->skb); + + rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_desc_write(entry_priv->desc, 1, word); +} + static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1515,59 +1549,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - entry_priv = intf->beacon->priv_data; - - /* - * 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); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Enable beacon generation. - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1592,7 +1573,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, - .beacon_update = rt2400pci_beacon_update, .tx_last_beacon = rt2400pci_tx_last_beacon, }; @@ -1610,6 +1590,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_tuner = rt2400pci_link_tuner, .write_tx_desc = rt2400pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt2400pci_write_beacon, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_filter = rt2400pci_config_filter, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0f2a0e22fd71..aa6dfb811c71 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1227,6 +1227,40 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt2500pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_pci *entry_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + u32 word; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + + /* + * Replace rt2x00lib allocated descriptor with the + * pointer to the _real_ hardware descriptor. + * After that, map the beacon to DMA and update the + * descriptor. + */ + memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry_priv->desc; + + rt2x00queue_map_txskb(rt2x00dev, entry->skb); + + rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_desc_write(entry_priv->desc, 1, word); +} + static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1808,60 +1842,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - entry_priv = intf->beacon->priv_data; - - /* - * 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); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Enable beacon generation. - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1886,7 +1866,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, - .beacon_update = rt2500pci_beacon_update, .tx_last_beacon = rt2500pci_tx_last_beacon, }; @@ -1904,6 +1883,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_tuner = rt2500pci_link_tuner, .write_tx_desc = rt2500pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt2500pci_write_beacon, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_filter = rt2500pci_config_filter, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 367db10b96d9..3558cb210747 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1107,6 +1107,65 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 0, word); } +/* + * TX data initialization + */ +static void rt2500usb_beacondone(struct urb *urb); + +static void rt2500usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + 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 length; + u16 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + + /* + * USB devices cannot blindly pass the skb->len as the + * 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); + + usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, + entry->skb->data, length, rt2500usb_beacondone, + entry); + + /* + * Second we need to create the guardian byte. + * We only need a single byte, so lets recycle + * the 'flags' field we are not using for beacons. + */ + bcn_priv->guardian_data = 0; + usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, + &bcn_priv->guardian_data, 1, rt2500usb_beacondone, + entry); + + /* + * Send out the guardian byte. + */ + usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); +} + static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { @@ -1122,9 +1181,6 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, return length; } -/* - * TX data initialization - */ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1679,96 +1735,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) return 0; } -/* - * IEEE80211 stack callback functions. - */ -static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_usb_bcn *bcn_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - int pipe = usb_sndbulkpipe(usb_dev, 1); - int length; - u16 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - bcn_priv = intf->beacon->priv_data; - - /* - * 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); - memset(skb->data, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = skb->data; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - - /* - * USB devices cannot blindly pass the skb->len as the - * length of the data to usb_fill_bulk_urb. Pass the skb - * to the driver to determine what the length should be. - */ - length = rt2500usb_get_tx_data_len(rt2x00dev, skb); - - usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, - intf->beacon); - - /* - * Second we need to create the guardian byte. - * We only need a single byte, so lets recycle - * the 'flags' field we are not using for beacons. - */ - bcn_priv->guardian_data = 0; - usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, - &bcn_priv->guardian_data, 1, rt2500usb_beacondone, - intf->beacon); - - /* - * Send out the guardian byte. - */ - usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); - - /* - * Enable beacon generation. - */ - rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static const struct ieee80211_ops rt2500usb_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -1782,7 +1748,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, - .beacon_update = rt2500usb_beacon_update, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1797,6 +1762,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_tuner = rt2500usb_link_tuner, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c07d9ef383f0..9fab0df18c3c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -364,6 +364,8 @@ struct rt2x00_intf { #define DELAYED_UPDATE_BEACON 0x00000001 #define DELAYED_CONFIG_ERP 0x00000002 #define DELAYED_LED_ASSOC 0x00000004 + + u16 seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -434,6 +436,7 @@ struct rt2x00lib_conf { */ struct rt2x00lib_erp { int short_preamble; + int cts_protection; int ack_timeout; int ack_consume_time; @@ -520,6 +523,7 @@ struct rt2x00lib_ops { struct sk_buff *skb, 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); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, @@ -910,39 +914,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); /** - * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input - * @entry: The entry which will be used to transfer the TX frame. - * @txdesc: rt2x00 TX descriptor which will be initialized by this function. - * - * This function will initialize the &struct txentry_desc based on information - * from mac80211. This descriptor can then be used by rt2x00lib and the drivers - * to correctly initialize the hardware descriptor. - * Note that before calling this function the skb->cb array must be untouched - * by rt2x00lib. Only after this function completes will it be save to - * overwrite the skb->cb information. - * The reason for this is that mac80211 writes its own tx information into - * the skb->cb array, and this function will use that information to initialize - * the &struct txentry_desc structure. - */ -void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc); - -/** - * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware - * @entry: The entry which will be used to transfer the TX frame. - * @txdesc: TX descriptor which will be used to write hardware descriptor - * - * This function will write a TX descriptor initialized by - * &rt2x00queue_create_tx_descriptor to the hardware. After this call - * has completed the frame is now owned by the hardware, the hardware - * queue will have automatically be kicked unless this frame was generated - * by rt2x00lib, in which case the frame is "special" and must be kicked - * by the caller. - */ -void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc); - -/** * rt2x00queue_get_queue - Convert queue index to queue pointer * @rt2x00dev: Pointer to &struct rt2x00_dev. * @queue: rt2x00 queue index (see &enum data_queue_qid). diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48608e8cc8b4..f20ca712504f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -84,6 +84,8 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, memset(&erp, 0, sizeof(erp)); erp.short_preamble = bss_conf->use_short_preamble; + erp.cts_protection = bss_conf->use_cts_prot; + erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b48c04e80a38..8c93eb8353b0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - struct sk_buff *skb; struct ieee80211_bss_conf conf; int delayed_flags; @@ -435,12 +434,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - if (delayed_flags & DELAYED_UPDATE_BEACON) { - skb = ieee80211_beacon_get(rt2x00dev->hw, vif); - if (skb && - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb)) - dev_kfree_skb(skb); - } + if (delayed_flags & DELAYED_UPDATE_BEACON) + rt2x00queue_update_beacon(rt2x00dev, vif); if (delayed_flags & DELAYED_CONFIG_ERP) rt2x00lib_config_erp(rt2x00dev, intf, &conf); diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b971bc6e7ee2..bab05a56e7a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -100,6 +100,14 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, rt2x00dev->fw->data, rt2x00dev->fw->size); + + /* + * When the firmware is uploaded to the hardware the LED + * association status might have been triggered, for correct + * LED handling it should now be reset. + */ + rt2x00leds_led_assoc(rt2x00dev, false); + return retval; } diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index eae5ce1d4de3..f2c9b0e79b5f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -139,6 +139,14 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); /** + * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @vif: Interface for which the beacon should be updated. + */ +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif); + +/** * rt2x00queue_index_inc - Index incrementation function * @queue: Queue (&struct data_queue) to perform the action on. * @index: Index type (&enum queue_index) to perform the action on. diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3a1fb6d47e5d..77af1df5d899 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -96,6 +96,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; enum data_queue_qid qid = skb_get_queue_mapping(skb); + struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct data_queue *queue; u16 frame_control; @@ -151,6 +152,18 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } } + /* + * XXX: This is as wrong as the old mac80211 code was, + * due to beacons not getting sequence numbers assigned + * properly. + */ + if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + intf->seqno += 0x10; + ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + ieee80211hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + } + if (rt2x00queue_write_tx_frame(queue, skb)) { ieee80211_stop_queue(rt2x00dev->hw, qid); return NETDEV_TX_BUSY; @@ -348,7 +361,8 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); - int status; + int update_bssid = 0; + int status = 0; /* * Mac80211 might be calling this function while we are trying @@ -360,12 +374,13 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, spin_lock(&intf->lock); /* - * If the interface does not work in master mode, - * then the bssid value in the interface structure - * should now be set. + * conf->bssid can be NULL if coming from the internal + * beacon update routine. */ - if (conf->type != IEEE80211_IF_TYPE_AP) + if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { + update_bssid = 1; memcpy(&intf->bssid, conf->bssid, ETH_ALEN); + } spin_unlock(&intf->lock); @@ -375,17 +390,14 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, * values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ - rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, + update_bssid ? conf->bssid : NULL); /* - * We only need to initialize the beacon when master mode is enabled. + * Update the beacon. */ - if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) - return 0; - - status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon); - if (status) - dev_kfree_skb(conf->beacon); + if (conf->changed & IEEE80211_IFCC_BEACON) + status = rt2x00queue_update_beacon(rt2x00dev, vif); return status; } @@ -501,7 +513,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) { + if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_CTS_PROT)) { if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); else diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 3ddce538ef4a..7f442030f5ad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -108,12 +108,15 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { + if (!skb) + return; + rt2x00queue_unmap_skb(rt2x00dev, skb); dev_kfree_skb_any(skb); } -void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) +static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); @@ -237,10 +240,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->signal |= 0x08; } } -EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); -void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) +static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct data_queue *queue = entry->queue; struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; @@ -270,7 +272,6 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); } -EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) { @@ -320,6 +321,60 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) return 0; } +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif) +{ + struct rt2x00_intf *intf = vif_to_intf(vif); + struct skb_frame_desc *skbdesc; + struct txentry_desc txdesc; + __le32 desc[16]; + + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); + if (!intf->beacon->skb) + return -ENOMEM; + + /* + * Copy all TX descriptor information into txdesc, + * after that we are free to use the skb->cb array + * for our information. + */ + rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); + + /* + * For the descriptor we use a local array from where the + * driver can move it to the correct location required for + * the hardware. + */ + memset(desc, 0, sizeof(desc)); + + /* + * Fill in skb descriptor + */ + skbdesc = get_skb_frame_desc(intf->beacon->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->desc = desc; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + + /* + * Write TX descriptor into reserved room in front of the beacon. + */ + rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); + + /* + * Send beacon to hardware. + * Also enable beacon generation, which might have been disabled + * by the driver during the config_beacon() callback function. + */ + rt2x00dev->ops->lib->write_beacon(intf->beacon); + rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); + + return 0; +} + struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 5a1330c5de71..70ef7bf434ab 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1600,6 +1600,41 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt61pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_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); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base, + skbdesc->desc, skbdesc->desc_len); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base + skbdesc->desc_len, + entry->skb->data, entry->skb->len); + + /* + * Clean up beacon skb. + */ + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; +} + static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -2355,72 +2390,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - unsigned int beacon_base; - 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); - - entry_priv = intf->beacon->priv_data; - memset(entry_priv->desc, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_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); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - - /* - * 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); - rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, - skbdesc->desc, skbdesc->desc_len); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base + skbdesc->desc_len, - skb->data, skb->len); - rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); - - /* - * Clean up beacon skb. - */ - dev_kfree_skb_any(skb); - intf->beacon->skb = NULL; - - return 0; -} - static const struct ieee80211_ops rt61pci_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -2436,7 +2405,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, - .beacon_update = rt61pci_beacon_update, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -2456,6 +2424,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_tuner = rt61pci_link_tuner, .write_tx_desc = rt61pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt61pci_write_beacon, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_filter = rt61pci_config_filter, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 25d8b660051f..34c6ff27afc4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1343,6 +1343,49 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 0, word); } +/* + * TX data initialization + */ +static void rt73usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt73usb_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); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, beacon_base, 0, + entry->skb->data, entry->skb->len, + REGISTER_TIMEOUT32(entry->skb->len)); + + /* + * Clean up the beacon skb. + */ + dev_kfree_skb(entry->skb); + entry->skb = NULL; +} + static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { @@ -1358,9 +1401,6 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, return length; } -/* - * TX data initialization - */ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1958,73 +1998,6 @@ 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 rt2x00_dev *rt2x00dev = hw->priv; - 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; - 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); - memset(skb->data, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = skb->data; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt73usb_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); - - /* - * 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); - rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, 0, - 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; -} - static const struct ieee80211_ops rt73usb_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -2040,7 +2013,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, - .beacon_update = rt73usb_beacon_update, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2058,6 +2030,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .link_tuner = rt73usb_link_tuner, .write_tx_desc = rt73usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, |