static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band) { const struct rt2x00_rate *rate; unsigned int i; u32 mask = 0; for (i = 0; i < band->n_bitrates; i++) { rate = rt2x00_get_rate(band->bitrates[i].hw_value); if (rate->flags & DEV_RATE_BASIC) mask |= rate->ratemask; } return mask; }
static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, struct rxdone_entry_desc *rxdesc) { struct ieee80211_supported_band *sband; const struct rt2x00_rate *rate; unsigned int i; int signal = rxdesc->signal; int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); switch (rxdesc->rate_mode) { case RATE_MODE_CCK: case RATE_MODE_OFDM: /* * For non-HT rates the MCS value needs to contain the * actually used rate modulation (CCK or OFDM). */ if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) signal = RATE_MCS(rxdesc->rate_mode, signal); sband = &rt2x00dev->bands[rt2x00dev->curr_band]; for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); if (((type == RXDONE_SIGNAL_PLCP) && (rate->plcp == signal)) || ((type == RXDONE_SIGNAL_BITRATE) && (rate->bitrate == signal)) || ((type == RXDONE_SIGNAL_MCS) && (rate->mcs == signal))) { return i; } } break; case RATE_MODE_HT_MIX: case RATE_MODE_HT_GREENFIELD: if (signal >= 0 && signal <= 76) return signal; break; default: break; } WARNING(rt2x00dev, "Frame received with unrecognized signal, " "mode=0x%.4x, signal=0x%.4x, type=%d.\n", rxdesc->rate_mode, signal, type); return 0; }
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, struct hw_mode_spec *spec) { struct ieee80211_hw *hw = rt2x00dev->hw; struct ieee80211_channel *channels; struct ieee80211_rate *rates; unsigned int num_rates; unsigned int i; num_rates = 0; if (spec->supported_rates & SUPPORT_RATE_CCK) num_rates += 4; if (spec->supported_rates & SUPPORT_RATE_OFDM) num_rates += 8; channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL); if (!channels) return -ENOMEM; rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL); if (!rates) goto exit_free_channels; /* * Initialize Rate list. */ for (i = 0; i < num_rates; i++) rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i)); /* * Initialize Channel list. */ for (i = 0; i < spec->num_channels; i++) { rt2x00lib_channel(&channels[i], spec->channels[i].channel, spec->channels_info[i].max_power, i); } /* * Intitialize 802.11b, 802.11g * Rates: CCK, OFDM. * Channels: 2.4 GHz */ if (spec->supported_bands & SUPPORT_BAND_2GHZ) { rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14; rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates; rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels; rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, &spec->ht, sizeof(spec->ht)); } /* * Intitialize 802.11a * Rates: OFDM. * Channels: OFDM, UNII, HiperLAN2. */ if (spec->supported_bands & SUPPORT_BAND_5GHZ) { rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates = num_rates - 4; rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14]; rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, &spec->ht, sizeof(spec->ht)); } return 0; exit_free_channels: kfree(channels); ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n"); return -ENOMEM; }
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 {
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; const struct rt2x00_rate *rate; unsigned int header_size; unsigned int align; unsigned int i; int idx = -1; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. */ skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); if (!skb) return; /* * Unmap the skb. */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); /* * Extract the RXD details. */ memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_size = ieee80211_get_hdrlen_from_skb(entry->skb); align = ((unsigned long)(entry->skb->data + header_size)) & 3; if (align) { skb_push(entry->skb, align); /* Move entire frame in 1 command */ memmove(entry->skb->data, entry->skb->data + align, rxdesc.size); } /* Update data pointers, trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); /* * Update RX statistics. */ sband = &rt2x00dev->bands[rt2x00dev->curr_band]; for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && (rate->plcp == rxdesc.signal)) || (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && (rate->bitrate == rxdesc.signal))) { idx = i; break; } } if (idx < 0) { WARNING(rt2x00dev, "Frame received with unrecognized signal," "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); idx = 0; } /* * Only update link status if this is a beacon frame carrying our bssid. */ hdr = (struct ieee80211_hdr *)entry->skb->data; if (ieee80211_is_beacon(hdr->frame_control) && (rxdesc.dev_flags & RXDONE_MY_BSS)) rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); rt2x00dev->link.qual.rx_success++; rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = idx; rx_status->qual = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* * Send frame to mac80211 & debugfs. * mac80211 will clean up the skb structure. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); /* * Replace the skb with the freshly allocated one. */ entry->skb = skb; entry->flags = 0; rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); rt2x00queue_index_inc(entry->queue, Q_INDEX); }