void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); /* * Don't allow interfaces to be remove while * either the device has disappeared or when * no interface is present. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) return; if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count--; else rt2x00dev->intf_sta_count--; /* * Release beacon entry so it is available for * new interfaces again. */ clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); /* * Make sure the bssid and mac address registers * are cleared to prevent false ACKing of frames. */ rt2x00lib_config_intf(rt2x00dev, intf, NL80211_IFTYPE_UNSPECIFIED, NULL, NULL); }
static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); int delayed_flags; /* * Copy all data we need during this action under the protection * of a spinlock. Otherwise race conditions might occur which results * into an invalid configuration. */ spin_lock(&intf->lock); delayed_flags = intf->delayed_flags; intf->delayed_flags = 0; spin_unlock(&intf->lock); /* * It is possible the radio was disabled while the work had been * scheduled. If that happens we should return here immediately, * note that in the spinlock protected area above the delayed_flags * have been cleared correctly. */ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; if (delayed_flags & DELAYED_UPDATE_BEACON) rt2x00queue_update_beacon(rt2x00dev, vif, true); }
static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, struct txentry_desc *txdesc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); unsigned long irqflags; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) || unlikely(!tx_info->control.vif)) return; /* * Hardware should insert sequence counter. * FIXME: We insert a software sequence counter first for * hardware that doesn't support hardware sequence counting. * * This is wrong because beacons are not getting sequence * numbers assigned properly. * * A secondary problem exists for drivers that cannot toggle * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ spin_lock_irqsave(&intf->seqlock, irqflags); if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(intf->seqno); spin_unlock_irqrestore(&intf->seqlock, irqflags); __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); }
static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; priv_tx = intf->beacon->priv_data; /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data; skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->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); /* * 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); /* * Enable beacon generation. * Write entire beacon with descriptor to register, * and kick the beacon generator. */ memcpy(priv_tx->data, skb->data, skb->len); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); return 0; }
static void rt2x00mac_set_tim_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_intf *intf = vif_to_intf(vif); if (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_ADHOC && vif->type != NL80211_IFTYPE_MESH_POINT && vif->type != NL80211_IFTYPE_WDS) return; set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags); }
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); unsigned int delayed = 0; /* * When the association status has changed we must reset the link * tuner counter. This is because some drivers determine if they * should perform link tuning based on the number of seconds * while associated or not associated. */ if (changes & BSS_CHANGED_ASSOC) { rt2x00dev->link.count = 0; if (bss_conf->assoc) rt2x00dev->intf_associated++; else rt2x00dev->intf_associated--; if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); else delayed |= DELAYED_LED_ASSOC; } /* * 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 | BSS_CHANGED_ERP_CTS_PROT)) { if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); else delayed |= DELAYED_CONFIG_ERP; } spin_lock(&intf->lock); memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); if (delayed) { intf->delayed_flags |= delayed; schedule_work(&rt2x00dev->intf_work); } spin_unlock(&intf->lock); }
/* * Interrupt context handlers. */ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_intf *intf = vif_to_intf(vif); if (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_ADHOC && vif->type != NL80211_IFTYPE_MESH_POINT && vif->type != NL80211_IFTYPE_WDS) return; spin_lock(&intf->lock); intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); }
static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags)) { /* * rt2800 has a H/W (or F/W) bug, device incorrectly increase * seqno on retransmited data (non-QOS) frames. To workaround * the problem let's generate seqno in software if QOS is * disabled. */ if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags)) __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); else /* H/W will generate sequence number */ return; } /* * The hardware is not able to insert a sequence number. Assign a * software generated one here. * * This is wrong because beacons are not getting sequence * numbers assigned properly. * * A secondary problem exists for drivers that cannot toggle * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ spin_lock(&intf->seqlock); if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(intf->seqno); spin_unlock(&intf->seqlock); }
int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); int update_bssid = 0; int status = 0; /* * Mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return 0; spin_lock(&intf->lock); /* * conf->bssid can be NULL if coming from the internal * beacon update routine. */ if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { update_bssid = 1; memcpy(&intf->bssid, conf->bssid, ETH_ALEN); } spin_unlock(&intf->lock); /* * Call rt2x00_config_intf() outside of the spinlock context since * the call will sleep for USB drivers. By using the ieee80211_if_conf * values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, update_bssid ? conf->bssid : NULL); /* * Update the beacon. */ if (conf->changed & IEEE80211_IFCC_BEACON) status = rt2x00queue_update_beacon(rt2x00dev, vif); return status; }
static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); /* * It is possible the radio was disabled while the work had been * scheduled. If that happens we should return here immediately, * note that in the spinlock protected area above the delayed_flags * have been cleared correctly. */ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) rt2x00queue_update_beacon(rt2x00dev, vif); }
/* * Interrupt context handlers. */ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); if (vif->type != IEEE80211_IF_TYPE_AP && vif->type != IEEE80211_IF_TYPE_IBSS) return; /* * Clean up the beacon skb. */ rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); intf->beacon->skb = NULL; spin_lock(&intf->lock); intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); }
static void rt2x00lib_resume_intf(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); spin_lock(&intf->lock); rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, intf->bssid); /* * Master or Ad-hoc mode require a new beacon update. */ if (vif->type == IEEE80211_IF_TYPE_AP || vif->type == IEEE80211_IF_TYPE_IBSS) intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); }
static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, struct txentry_desc *txdesc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); unsigned long irqflags; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags)) return; /* * The hardware is not able to insert a sequence number. Assign a * software generated one here. * * This is wrong because beacons are not getting sequence * numbers assigned properly. * * A secondary problem exists for drivers that cannot toggle * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ spin_lock_irqsave(&intf->seqlock, irqflags); if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(intf->seqno); spin_unlock_irqrestore(&intf->seqlock, irqflags); }
static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); u16 seqno; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags)) return; /* * The hardware is not able to insert a sequence number. Assign a * software generated one here. * * This is wrong because beacons are not getting sequence * numbers assigned properly. * * A secondary problem exists for drivers that cannot toggle * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) seqno = atomic_add_return(0x10, &intf->seqno); else seqno = atomic_read(&intf->seqno); hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seqno); }
int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); struct queue_entry *entry = NULL; unsigned int i; /* * Don't allow interfaces to be added * the device has disappeared. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) return -ENODEV; switch (vif->type) { case NL80211_IFTYPE_AP: /* * We don't support mixed combinations of * sta and ap interfaces. */ if (rt2x00dev->intf_sta_count) return -ENOBUFS; /* * Check if we exceeded the maximum amount * of supported interfaces. */ if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) return -ENOBUFS; break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_WDS: /* * We don't support mixed combinations of * sta and ap interfaces. */ if (rt2x00dev->intf_ap_count) return -ENOBUFS; /* * Check if we exceeded the maximum amount * of supported interfaces. */ if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) return -ENOBUFS; break; default: return -EINVAL; } /* * Loop through all beacon queues to find a free * entry. Since there are as much beacon entries * as the maximum interfaces, this search shouldn't * fail. */ for (i = 0; i < queue->limit; i++) { entry = &queue->entries[i]; if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) break; } if (unlikely(i == queue->limit)) return -ENOBUFS; /* * We are now absolutely sure the interface can be created, * increase interface count and start initialization. */ if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count++; else rt2x00dev->intf_sta_count++; spin_lock_init(&intf->lock); spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; /* * The MAC adddress must be configured after the device * has been initialized. Otherwise the device can reset * the MAC registers. * The BSSID address must only be configured in AP mode, * however we should not send an empty BSSID address for * STA interfaces at this time, since this can cause * invalid behavior in the device. */ memcpy(&intf->mac, vif->addr, ETH_ALEN); if (vif->type == NL80211_IFTYPE_AP) { memcpy(&intf->bssid, vif->addr, ETH_ALEN); rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, intf->bssid); } else { rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); } /* * Some filters depend on the current working mode. We can force * an update during the next configure_filter() run by mac80211 by * resetting the current packet_filter state. */ rt2x00dev->packet_filter = 0; return 0; }
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); /* * mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return; /* * Update the BSSID. */ if (changes & BSS_CHANGED_BSSID) rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, bss_conf->bssid); /* * Start/stop beaconing. */ if (changes & BSS_CHANGED_BEACON_ENABLED) { if (!bss_conf->enable_beacon && intf->enable_beacon) { rt2x00dev->intf_beaconing--; intf->enable_beacon = false; /* * Clear beacon in the H/W for this vif. This is needed * to disable beaconing on this particular interface * and keep it running on other interfaces. */ rt2x00queue_clear_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 0) { /* * Last beaconing interface disabled * -> stop beacon queue. */ mutex_lock(&intf->beacon_skb_mutex); rt2x00queue_stop_queue(rt2x00dev->bcn); mutex_unlock(&intf->beacon_skb_mutex); } } else if (bss_conf->enable_beacon && !intf->enable_beacon) { rt2x00dev->intf_beaconing++; intf->enable_beacon = true; /* * Upload beacon to the H/W. This is only required on * USB devices. PCI devices fetch beacons periodically. */ if (rt2x00_is_usb(rt2x00dev)) rt2x00queue_update_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 1) { /* * First beaconing interface enabled * -> start beacon queue. */ mutex_lock(&intf->beacon_skb_mutex); rt2x00queue_start_queue(rt2x00dev->bcn); mutex_unlock(&intf->beacon_skb_mutex); } } } /* * When the association status has changed we must reset the link * tuner counter. This is because some drivers determine if they * should perform link tuning based on the number of seconds * while associated or not associated. */ if (changes & BSS_CHANGED_ASSOC) { rt2x00dev->link.count = 0; if (bss_conf->assoc) rt2x00dev->intf_associated++; else rt2x00dev->intf_associated--; rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); } /* * Check for access point which do not support 802.11e . We have to * generate data frames sequence number in S/W for such AP, because * of H/W bug. */ if (changes & BSS_CHANGED_QOS && !bss_conf->qos) set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); /* * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); }
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); struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; struct ieee80211_rate *rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); const struct rt2x00_rate *hwrate; unsigned int data_length; unsigned int duration; unsigned int residual; unsigned long irqflags; memset(txdesc, 0, sizeof(*txdesc)); /* * Initialize information from queue */ txdesc->queue = entry->queue->qid; txdesc->cw_min = entry->queue->cw_min; txdesc->cw_max = entry->queue->cw_max; txdesc->aifs = entry->queue->aifs; /* Data length should be extended with 4 bytes for CRC */ data_length = entry->skb->len + 4; /* * Check whether this frame is to be acked. */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) __set_bit(ENTRY_TXD_ACK, &txdesc->flags); /* * Check if this is a RTS/CTS frame */ if (ieee80211_is_rts(hdr->frame_control) || ieee80211_is_cts(hdr->frame_control)) { __set_bit(ENTRY_TXD_BURST, &txdesc->flags); if (ieee80211_is_rts(hdr->frame_control)) __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); else __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); if (tx_info->control.rts_cts_rate_idx >= 0) rate = ieee80211_get_rts_cts_rate(rt2x00dev->hw, tx_info); } /* * Determine retry information. */ txdesc->retry_limit = tx_info->control.retry_limit; if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); /* * Check if more fragments are pending */ if (ieee80211_has_morefrags(hdr->frame_control)) { __set_bit(ENTRY_TXD_BURST, &txdesc->flags); __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); } /* * Beacons and probe responses require the tsf timestamp * to be inserted into the frame. */ if (ieee80211_is_beacon(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control)) __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); /* * Determine with what IFS priority this frame should be send. * Set ifs to IFS_SIFS when the this is not the first fragment, * or this fragment came after RTS/CTS. */ if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { txdesc->ifs = IFS_SIFS; } else if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) { __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); txdesc->ifs = IFS_BACKOFF; } else { txdesc->ifs = IFS_SIFS; } /* * Hardware should insert sequence counter. * FIXME: We insert a software sequence counter first for * hardware that doesn't support hardware sequence counting. * * This is wrong because beacons are not getting sequence * numbers assigned properly. * * A secondary problem exists for drivers that cannot toggle * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { spin_lock_irqsave(&intf->seqlock, irqflags); if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(intf->seqno); spin_unlock_irqrestore(&intf->seqlock, irqflags); __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); } /* * PLCP setup * Length calculation depends on OFDM/CCK rate. */ hwrate = rt2x00_get_rate(rate->hw_value); txdesc->signal = hwrate->plcp; txdesc->service = 0x04; if (hwrate->flags & DEV_RATE_OFDM) { __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); txdesc->length_high = (data_length >> 6) & 0x3f; txdesc->length_low = data_length & 0x3f; } else {
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); int (*set_key) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); struct rt2x00lib_crypto crypto; static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) return -EOPNOTSUPP; else if (key->keylen > 32) return -ENOSPC; memset(&crypto, 0, sizeof(crypto)); /* * When in STA mode, bssidx is always 0 otherwise local_address[5] * contains the bss number, see BSS_ID_MASK comments for details. */ if (rt2x00dev->intf_sta_count) crypto.bssidx = 0; else crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) return -EOPNOTSUPP; crypto.cmd = cmd; if (sta) { /* some drivers need the AID */ crypto.aid = sta->aid; crypto.address = sta->addr; } else crypto.address = bcast_addr; if (crypto.cipher == CIPHER_TKIP) memcpy_tkip(&crypto, &key->key[0], key->keylen); else memcpy(&crypto.key, &key->key[0], key->keylen); /* * Each BSS has a maximum of 4 shared keys. * Shared key index values: * 0) BSS0 key0 * 1) BSS0 key1 * ... * 4) BSS1 key0 * ... * 8) BSS2 key0 * ... * Both pairwise as shared key indeces are determined by * driver. This is required because the hardware requires * keys to be assigned in correct order (When key 1 is * provided but key 0 is not, then the key is not found * by the hardware during RX). */ if (cmd == SET_KEY) key->hw_key_idx = 0; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) set_key = rt2x00dev->ops->lib->config_pairwise_key; else set_key = rt2x00dev->ops->lib->config_shared_key; if (!set_key) return -EOPNOTSUPP; return set_key(rt2x00dev, &crypto, key); }
int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); struct data_queue *queue = rt2x00dev->bcn; struct queue_entry *entry = NULL; unsigned int i; /* * Don't allow interfaces to be added * the device has disappeared. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) return -ENODEV; /* * Loop through all beacon queues to find a free * entry. Since there are as much beacon entries * as the maximum interfaces, this search shouldn't * fail. */ for (i = 0; i < queue->limit; i++) { entry = &queue->entries[i]; if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) break; } if (unlikely(i == queue->limit)) return -ENOBUFS; /* * We are now absolutely sure the interface can be created, * increase interface count and start initialization. */ if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count++; else rt2x00dev->intf_sta_count++; mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; /* * The MAC address must be configured after the device * has been initialized. Otherwise the device can reset * the MAC registers. * The BSSID address must only be configured in AP mode, * however we should not send an empty BSSID address for * STA interfaces at this time, since this can cause * invalid behavior in the device. */ rt2x00lib_config_intf(rt2x00dev, intf, vif->type, vif->addr, NULL); /* * Some filters depend on the current working mode. We can force * an update during the next configure_filter() run by mac80211 by * resetting the current packet_filter state. */ rt2x00dev->packet_filter = 0; return 0; }
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); /* * mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return; spin_lock(&intf->lock); /* * conf->bssid can be NULL if coming from the internal * beacon update routine. */ if (changes & BSS_CHANGED_BSSID) memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); spin_unlock(&intf->lock); /* * Call rt2x00_config_intf() outside of the spinlock context since * the call will sleep for USB drivers. By using the ieee80211_if_conf * values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ if (changes & BSS_CHANGED_BSSID) rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, bss_conf->bssid); /* * Update the beacon. */ if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) rt2x00queue_update_beacon(rt2x00dev, vif, bss_conf->enable_beacon); /* * When the association status has changed we must reset the link * tuner counter. This is because some drivers determine if they * should perform link tuning based on the number of seconds * while associated or not associated. */ if (changes & BSS_CHANGED_ASSOC) { rt2x00dev->link.count = 0; if (bss_conf->assoc) rt2x00dev->intf_associated++; else rt2x00dev->intf_associated--; rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); } /* * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); }