Beispiel #1
0
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;
}
Beispiel #4
0
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);
}