Example #1
0
static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
				   struct ieee80211_sta *sta,
				   struct sk_buff *skb,
				   u16 hw_queue)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct rtl_tx_desc *pdesc = NULL;
	struct rtl_tcb_desc tcb_desc;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	__le16 fc = hdr->frame_control;
	u8 *pda_addr = hdr->addr1;
	/* ssn */
	u8 *qc = NULL;
	u8 tid = 0;
	u16 seq_number = 0;

	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
	if (ieee80211_is_auth(fc)) {
		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
		rtl_ips_nic_on(hw);
	}

	if (rtlpriv->psc.sw_ps_enabled) {
		if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) &&
		    !ieee80211_has_pm(fc))
			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
	}

	rtl_action_proc(hw, skb, true);
	if (is_multicast_ether_addr(pda_addr))
		rtlpriv->stats.txbytesmulticast += skb->len;
	else if (is_broadcast_ether_addr(pda_addr))
		rtlpriv->stats.txbytesbroadcast += skb->len;
	else
		rtlpriv->stats.txbytesunicast += skb->len;
	if (ieee80211_is_data_qos(fc)) {
		qc = ieee80211_get_qos_ctl(hdr);
		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
		seq_number = (le16_to_cpu(hdr->seq_ctrl) &
			     IEEE80211_SCTL_SEQ) >> 4;
		seq_number += 1;
		seq_number <<= 4;
	}
	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, NULL, info, sta, skb,
					hw_queue, &tcb_desc);
	if (!ieee80211_has_morefrags(hdr->frame_control)) {
		if (qc)
			mac->tids[tid].seq_number = seq_number;
	}
	if (ieee80211_is_data(fc))
		rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX);
}
Example #2
0
void wcn36xx_fill_tx_bd(struct wcn36xx *wcn, struct wcn36xx_tx_bd *bd,
			u8 broadcast, u8 encrypt, struct ieee80211_hdr *hdr,
			bool tx_compl)
{
	bd->dpu_rf = WCN36XX_BMU_WQ_TX;
	bd->pdu.tid   = WCN36XX_TID;
	bd->pdu.reserved3 = 0xd;

	if (broadcast) {
		/* broadcast */
		bd->ub = 1;
		bd->queue_id = WCN36XX_TX_B_WQ_ID;

		/* default rate for broadcast */
		if (ieee80211_is_mgmt(hdr->frame_control))
			bd->bd_rate = (wcn->band == IEEE80211_BAND_5GHZ) ?
				WCN36XX_BD_RATE_CTRL :
				WCN36XX_BD_RATE_MGMT;
		/* No ack needed not unicast */
		bd->ack_policy = 1;
	} else {
		bd->queue_id = WCN36XX_TX_U_WQ_ID;
		/* default rate for unicast */
		bd->ack_policy = 0;
		if (ieee80211_is_data(hdr->frame_control))
			bd->bd_rate = WCN36XX_BD_RATE_DATA;
		else if (ieee80211_is_mgmt(hdr->frame_control))
			bd->bd_rate = (wcn->band == IEEE80211_BAND_5GHZ) ?
				WCN36XX_BD_RATE_CTRL :
				WCN36XX_BD_RATE_MGMT;
		else if (ieee80211_is_ctl(hdr->frame_control))
			bd->bd_rate = WCN36XX_BD_RATE_CTRL;
		else
			wcn36xx_warn("frame control type unknown");
	}

	if (ieee80211_is_data(hdr->frame_control)) {
		bd->dpu_sign = wcn->current_vif->ucast_dpu_signature;
		bd->queue_id = 0;
		bd->sta_index = wcn->current_vif->sta_index;
		bd->dpu_desc_idx = wcn->current_vif->dpu_desc_index;
	} else {
		bd->sta_index = wcn->current_vif->self_sta_index;
		bd->dpu_desc_idx = wcn->current_vif->self_dpu_desc_index;
	}

	bd->dpu_ne = encrypt;
	bd->tx_comp = tx_compl;

	buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
	bd->tx_bd_sign = 0xbdbdbdbd;
}
Example #3
0
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
{
	unsigned int hdrlen = 24;

	if (ieee80211_is_data(fc)) {
		if (ieee80211_has_a4(fc))
			hdrlen = 30;
		if (ieee80211_is_data_qos(fc)) {
			hdrlen += IEEE80211_QOS_CTL_LEN;
			if (ieee80211_has_order(fc))
				hdrlen += IEEE80211_HT_CTL_LEN;
		}
		goto out;
	}

	if (ieee80211_is_ctl(fc)) {
		/*
		 * ACK and CTS are 10 bytes, all others 16. To see how
		 * to get this condition consider
		 *   subtype mask:   0b0000000011110000 (0x00F0)
		 *   ACK subtype:    0b0000000011010000 (0x00D0)
		 *   CTS subtype:    0b0000000011000000 (0x00C0)
		 *   bits that matter:         ^^^      (0x00E0)
		 *   value of those: 0b0000000011000000 (0x00C0)
		 */
		if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
			hdrlen = 10;
		else
			hdrlen = 16;
	}
out:
	return hdrlen;
}
Example #4
0
/*
 * Function to decode the layer 2 header in the packet.
 * You need to fill out:
 * - ctx->l2len
 * - ctx->srcaddr
 * - ctx->dstaddr
 * - ctx->proto
 * - ctx->decoded_extra
 * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
 */
int 
dlt_ieee80211_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
{
    assert(ctx);
    assert(packet);
    assert(pktlen >= dlt_ieee80211_l2len(ctx, packet, pktlen));

    dbgx(3, "Decoding 802.11 packet " COUNTER_SPEC, ctx->tcpedit->runtime.packetnum);
    if (! ieee80211_is_data(ctx, packet, pktlen)) {
        tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is not a normal 802.11 data frame",
            ctx->tcpedit->runtime.packetnum);
        return TCPEDIT_SOFT_ERROR;
    }
    
    if (ieee80211_is_encrypted(ctx, packet, pktlen)) {
        tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is encrypted.  Unable to decode frame.",
            ctx->tcpedit->runtime.packetnum);
        return TCPEDIT_SOFT_ERROR;
    }

    ctx->l2len = dlt_ieee80211_l2len(ctx, packet, pktlen);
    memcpy(&(ctx->srcaddr), ieee80211_get_src((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN);
    memcpy(&(ctx->dstaddr), ieee80211_get_dst((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN);
    ctx->proto = dlt_ieee80211_proto(ctx, packet, pktlen);

    return TCPEDIT_OK; /* success */
}
static void rtl_get_rate( void *ppriv, struct ieee80211_sta *sta,
			 void *priv_sta, struct ieee80211_tx_rate_control *txrc )
{
	struct rtl_priv *rtlpriv = ppriv;
	struct sk_buff *skb = txrc->skb;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB( skb );
	struct ieee80211_tx_rate *rates = tx_info->control.rates;
	__le16 fc = rtl_get_fc( skb );
	u8 try_per_rate, i, rix;
	bool not_data = !ieee80211_is_data( fc );

	if ( rate_control_send_low( sta, priv_sta, txrc ) )
		return;

	rix = _rtl_rc_get_highest_rix( rtlpriv, sta, skb, not_data );
	try_per_rate = 1;
	_rtl_rc_rate_set_series( rtlpriv, sta, &rates[0], txrc,
				try_per_rate, rix, 1, not_data );

	if ( !not_data ) {
		for ( i = 1; i < 4; i++ )
			_rtl_rc_rate_set_series( rtlpriv, sta, &rates[i],
						txrc, i, ( rix - i ), 1,
						not_data );
	}
}
Example #6
0
void ath_debug_rate_stats(struct ath_softc *sc,
			  struct ath_rx_status *rs,
			  struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ath_hw *ah = sc->sc_ah;
	struct ieee80211_rx_status *rxs;
	struct ath_rx_rate_stats *rstats;
	struct ieee80211_sta *sta;
	struct ath_node *an;

	if (!ieee80211_is_data(hdr->frame_control))
		return;

	rcu_read_lock();

	sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
	if (!sta)
		goto exit;

	an = (struct ath_node *) sta->drv_priv;
	rstats = &an->rx_rate_stats;
	rxs = IEEE80211_SKB_RXCB(skb);

	if (IS_HT_RATE(rs->rs_rate)) {
		if (rxs->rate_idx >= ARRAY_SIZE(rstats->ht_stats))
			goto exit;

		if (rxs->bw == RATE_INFO_BW_40)
			rstats->ht_stats[rxs->rate_idx].ht40_cnt++;
		else
			rstats->ht_stats[rxs->rate_idx].ht20_cnt++;

		if (rxs->enc_flags & RX_ENC_FLAG_SHORT_GI)
			rstats->ht_stats[rxs->rate_idx].sgi_cnt++;
		else
			rstats->ht_stats[rxs->rate_idx].lgi_cnt++;

		goto exit;
	}

	if (IS_CCK_RATE(rs->rs_rate)) {
		if (rxs->enc_flags & RX_ENC_FLAG_SHORTPRE)
			rstats->cck_stats[rxs->rate_idx].cck_sp_cnt++;
		else
			rstats->cck_stats[rxs->rate_idx].cck_lp_cnt++;

		goto exit;
	}

	if (IS_OFDM_RATE(rs->rs_rate)) {
		if (ah->curchan->chan->band == NL80211_BAND_2GHZ)
			rstats->ofdm_stats[rxs->rate_idx - 4].ofdm_cnt++;
		else
			rstats->ofdm_stats[rxs->rate_idx].ofdm_cnt++;
	}
exit:
	rcu_read_unlock();
}
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct ieee80211_sta *sta,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	struct ieee80211_rate *txrate;
	__le16 fc = hdr->frame_control;

	txrate = ieee80211_get_tx_rate(hw, info);
	if (txrate)
		tcb_desc->hw_rate = txrate->hw_value;
	else
		tcb_desc->hw_rate = 0;

	if (ieee80211_is_data(fc)) {

		if (info->control.rates[0].idx == 0 ||
				ieee80211_is_nullfunc(fc)) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;

			tcb_desc->disable_ratefallback = 1;
		} else {
			if (sta && (sta->ht_cap.ht_supported)) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->broadcast = 1;

		_rtl_txrate_selectmode(hw, sta, tcb_desc);
		_rtl_query_bandwidth_mode(hw, sta, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, sta, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;
		tcb_desc->packet_bw = false;
	}
}
Example #8
0
ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	u8 pn[CCMP_PN_LEN];
	int data_len;
	int queue;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control) &&
	    !ieee80211_is_robust_mgmt_frame(hdr))
		return RX_CONTINUE;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
		return RX_DROP_UNUSABLE;

	ccmp_hdr2pn(pn, skb->data + hdrlen);

	queue = rx->security_idx;

	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
		key->u.ccmp.replays++;
		return RX_DROP_UNUSABLE;
	}

	if (!(status->flag & RX_FLAG_DECRYPTED)) {
		u8 scratch[6 * AES_BLOCK_SIZE];
		/* hardware didn't decrypt/verify MIC */
		ccmp_special_blocks(skb, pn, scratch, 1);

		if (ieee80211_aes_ccm_decrypt(
			    key->u.ccmp.tfm, scratch,
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
			    skb->data + hdrlen + CCMP_HDR_LEN))
			return RX_DROP_UNUSABLE;
	}

	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);

	/* Remove CCMP header and MIC */
	skb_trim(skb, skb->len - CCMP_MIC_LEN);
	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
	skb_pull(skb, CCMP_HDR_LEN);

	return RX_CONTINUE;
}
Example #9
0
ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	u8 pn[CCMP_PN_LEN];
	int data_len;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
		return RX_DROP_UNUSABLE;

	if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
		return RX_CONTINUE;

	ccmp_hdr2pn(pn, skb->data + hdrlen);

	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
		key->u.ccmp.replays++;
		return RX_DROP_UNUSABLE;
	}

	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
		/* hardware didn't decrypt/verify MIC */
		ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);

		if (ieee80211_aes_ccm_decrypt(
			    key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
			    skb->data + hdrlen + CCMP_HDR_LEN))
			return RX_DROP_UNUSABLE;
	}

	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);

	/* Remove CCMP header and MIC */
	skb_trim(skb, skb->len - CCMP_MIC_LEN);
	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
	skb_pull(skb, CCMP_HDR_LEN);

	return RX_CONTINUE;
}
Example #10
0
ieee80211_rx_result
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen, res, hwaccel = 0, wpa_test = 0;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	if (!rx->sta || skb->len - hdrlen < 12)
		return RX_DROP_UNUSABLE;

	if (rx->status->flag & RX_FLAG_DECRYPTED) {
		if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
			/*
			 * Hardware took care of all processing, including
			 * replay protection, and stripped the ICV/IV so
			 * we cannot do any checks here.
			 */
			return RX_CONTINUE;
		}

		/* let TKIP code verify IV, but skip decryption */
		hwaccel = 1;
	}

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
					  skb->len - hdrlen, rx->sta->sta.addr,
					  hdr->addr1, hwaccel, rx->queue,
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
	if (res != TKIP_DECRYPT_OK || wpa_test)
		return RX_DROP_UNUSABLE;

	/* Trim ICV */
	skb_trim(skb, skb->len - TKIP_ICV_LEN);

	/* Remove IV */
	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
	skb_pull(skb, TKIP_IV_LEN);

	return RX_CONTINUE;
}
Example #11
0
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
			enum nl80211_iftype type)
{
	__le16 fc = hdr->frame_control;

	 /* drop ACK/CTS frames and incorrect hdr len (ctrl) */
	if (len < 16)
		return NULL;

	if (ieee80211_is_data(fc)) {
		if (len < 24) /* drop incorrect hdr len (data) */
			return NULL;

		if (ieee80211_has_a4(fc))
			return NULL;
		if (ieee80211_has_tods(fc))
			return hdr->addr1;
		if (ieee80211_has_fromds(fc))
			return hdr->addr2;

		return hdr->addr3;
	}

	if (ieee80211_is_mgmt(fc)) {
		if (len < 24) /* drop incorrect hdr len (mgmt) */
			return NULL;
		return hdr->addr3;
	}

	if (ieee80211_is_ctl(fc)) {
		if(ieee80211_is_pspoll(fc))
			return hdr->addr1;

		if (ieee80211_is_back_req(fc)) {
			switch (type) {
			case NL80211_IFTYPE_STATION:
				return hdr->addr2;
			case NL80211_IFTYPE_AP:
			case NL80211_IFTYPE_AP_VLAN:
				return hdr->addr1;
			default:
				break; /* fall through to the return */
			}
		}
	}

	return NULL;
}
Example #12
0
ieee80211_rx_result
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen, res, hwaccel = 0;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	int queue = rx->queue;

	/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
	if (rx->queue == NUM_RX_DATA_QUEUES - 1)
		queue = 0;

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if (!ieee80211_is_data(hdr->frame_control))
		return RX_CONTINUE;

	if (!rx->sta || skb->len - hdrlen < 12)
		return RX_DROP_UNUSABLE;

	/*
	 * Let TKIP code verify IV, but skip decryption.
	 * In the case where hardware checks the IV as well,
	 * we don't even get here, see ieee80211_rx_h_decrypt()
	 */
	if (status->flag & RX_FLAG_DECRYPTED)
		hwaccel = 1;

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
					  skb->len - hdrlen, rx->sta->sta.addr,
					  hdr->addr1, hwaccel, queue,
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
	if (res != TKIP_DECRYPT_OK)
		return RX_DROP_UNUSABLE;

	/* Trim ICV */
	skb_trim(skb, skb->len - TKIP_ICV_LEN);

	/* Remove IV */
	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
	skb_pull(skb, TKIP_IV_LEN);

	return RX_CONTINUE;
}
Example #13
0
File: rc.c Project: IDM350/linux
/*mac80211 Rate Control callbacks*/
static void rtl_tx_status(void *ppriv,
			  struct ieee80211_supported_band *sband,
			  struct ieee80211_sta *sta, void *priv_sta,
			  struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = ppriv;
	struct rtl_mac *mac = rtl_mac(rtlpriv);
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	__le16 fc = rtl_get_fc(skb);
	struct rtl_sta_info *sta_entry;

	if (!priv_sta || !ieee80211_is_data(fc))
		return;

	if (rtl_is_special_data(mac->hw, skb, true))
		return;

	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
		return;

	if (sta) {
		/* Check if aggregation has to be enabled for this tid */
		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
		if ((sta->ht_cap.ht_supported == true) &&
				!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
			if (ieee80211_is_data_qos(fc)) {
				u8 tid = rtl_get_tid(skb);
				if (_rtl_tx_aggr_check(rtlpriv, sta_entry,
						       tid)) {
					sta_entry->tids[tid].agg.agg_state =
						RTL_AGG_PROGRESS;
					/*<delete in kernel start>*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
					/*<delete in kernel end>*/
					ieee80211_start_tx_ba_session(sta, tid,
								      5000);
					/*<delete in kernel start>*/
#else
					ieee80211_start_tx_ba_session(sta, tid);
#endif
					/*<delete in kernel end>*/
				}
			}
		}
	}
}
Example #14
0
void ieee80211s_update_metric(struct ieee80211_local *local,
		struct sta_info *stainfo, struct sk_buff *skb)
{
	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	int failed;

	if (!ieee80211_is_data(hdr->frame_control))
		return;

	failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);

	/* moving average, scaled to 100 */
	stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
	if (stainfo->fail_avg > 95)
		mesh_plink_broken(stainfo);
}
Example #15
0
/* hard_start_xmit function for hostapd wlan#ap interfaces */
netdev_tx_t hostap_mgmt_start_xmit(struct sk_buff *skb,
				   struct net_device *dev)
{
	struct hostap_interface *iface;
	local_info_t *local;
	struct hostap_skb_tx_data *meta;
	struct ieee80211_hdr *hdr;
	u16 fc;

	iface = netdev_priv(dev);
	local = iface->local;

	if (skb->len < 10) {
		printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "
		       "(len=%d)\n", dev->name, skb->len);
		kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	iface->stats.tx_packets++;
	iface->stats.tx_bytes += skb->len;

	meta = (struct hostap_skb_tx_data *) skb->cb;
	memset(meta, 0, sizeof(*meta));
	meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
	meta->iface = iface;

	if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
		hdr = (struct ieee80211_hdr *) skb->data;
		fc = le16_to_cpu(hdr->frame_control);
		if (ieee80211_is_data(hdr->frame_control) &&
		    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DATA) {
			u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +
					     sizeof(rfc1042_header)];
			meta->ethertype = (pos[0] << 8) | pos[1];
		}
	}

	/* Send IEEE 802.11 encapsulated frame using the master radio device */
	skb->dev = local->dev;
	dev_queue_xmit(skb);
	return NETDEV_TX_OK;
}
Example #16
0
void ieee80211s_update_metric(struct ieee80211_local *local,
		struct sta_info *sta, struct sk_buff *skb)
{
	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	int failed;

	if (!ieee80211_is_data(hdr->frame_control))
		return;

	failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);

	/* moving average, scaled to 100.
	 * feed failure as 100 and success as 0
	 */
	ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, failed * 100);
	if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) >
			LINK_FAIL_THRESH)
		mesh_plink_broken(sta);
}
Example #17
0
/* Indicate which queue to use.  */
static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;

	if (!ieee80211_is_data(hdr->frame_control)) {
		/* management frames go on AC_VO queue, but are sent
		* without QoS control fields */
		return 0;
	}

	if (0 /* injected */) {
		/* use AC from radiotap */
	}

	if (!ieee80211_is_data_qos(hdr->frame_control)) {
		skb->priority = 0; /* required for correct WPA/11i MIC */
		return ieee802_1d_to_ac[skb->priority];
	}

	/* use the data classifier to determine what 802.1d tag the
	 * data frame has */
	skb->priority = cfg80211_classify8021d(skb);

	/* in case we are a client verify acm is not set for this ac */
	while (unlikely(local->wmm_acm & BIT(skb->priority))) {
		if (wme_downgrade_ac(skb)) {
			/*
			 * This should not really happen. The AP has marked all
			 * lower ACs to require admission control which is not
			 * a reasonable configuration. Allow the frame to be
			 * transmitted using AC_BK as a workaround.
			 */
			break;
		}
	}

	/* look up which queue to use for frames with this 1d tag */
	return ieee802_1d_to_ac[skb->priority];
}
Example #18
0
File: coex.c Project: Lyude/linux
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
			   struct ieee80211_tx_info *info, u8 ac)
{
	__le16 fc = hdr->frame_control;
	bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm);

	if (info->band != NL80211_BAND_2GHZ)
		return 0;

	if (unlikely(mvm->bt_tx_prio))
		return mvm->bt_tx_prio - 1;

	if (likely(ieee80211_is_data(fc))) {
		if (likely(ieee80211_is_data_qos(fc))) {
			switch (ac) {
			case IEEE80211_AC_BE:
				return mplut_enabled ? 1 : 0;
			case IEEE80211_AC_VI:
				return mplut_enabled ? 2 : 3;
			case IEEE80211_AC_VO:
				return 3;
			default:
				return 0;
			}
		} else if (is_multicast_ether_addr(hdr->addr1)) {
			return 3;
		} else
			return 0;
	} else if (ieee80211_is_mgmt(fc)) {
		return ieee80211_is_disassoc(fc) ? 0 : 3;
	} else if (ieee80211_is_ctl(fc)) {
		/* ignore cfend and cfendack frames as we never send those */
		return 3;
	}

	return 0;
}
Example #19
0
/* Indicate which queue to use.  */
static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;

	if (!ieee80211_is_data(hdr->frame_control)) {
		/* management frames go on AC_VO queue, but are sent
		* without QoS control fields */
		return 0;
	}

	if (0 /* injected */) {
		/* use AC from radiotap */
	}

	if (!ieee80211_is_data_qos(hdr->frame_control)) {
		skb->priority = 0; /* required for correct WPA/11i MIC */
		return ieee802_1d_to_ac[skb->priority];
	}

	/* use the data classifier to determine what 802.1d tag the
	 * data frame has */
	skb->priority = classify_1d(skb);

	/* in case we are a client verify acm is not set for this ac */
	while (unlikely(local->wmm_acm & BIT(skb->priority))) {
		if (wme_downgrade_ac(skb)) {
			/* The old code would drop the packet in this
			 * case.
			 */
			return 0;
		}
	}

	/* look up which queue to use for frames with this 1d tag */
	return ieee802_1d_to_ac[skb->priority];
}
Example #20
0
File: wme.c Project: 7799/linux
/* Indicate which queue to use for this fully formed 802.11 frame */
u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb,
				 struct ieee80211_hdr *hdr)
{
	struct ieee80211_local *local = sdata->local;
	u8 *p;

	if (local->hw.queues < IEEE80211_NUM_ACS)
		return 0;

	if (!ieee80211_is_data(hdr->frame_control)) {
		skb->priority = 7;
		return ieee802_1d_to_ac[skb->priority];
	}
	if (!ieee80211_is_data_qos(hdr->frame_control)) {
		skb->priority = 0;
		return ieee802_1d_to_ac[skb->priority];
	}

	p = ieee80211_get_qos_ctl(hdr);
	skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;

	return ieee80211_downgrade_queue(sdata, skb);
}
Example #21
0
static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	PSTxDesc head_td;
	u32 dma_idx = TYPE_AC0DMA;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);

	if (!ieee80211_is_data(hdr->frame_control))
		dma_idx = TYPE_TXDMA0;

	if (AVAIL_TD(priv, dma_idx) < 1) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return -ENOMEM;
	}

	head_td = priv->apCurrTD[dma_idx];

	head_td->m_td1TD1.byTCR = 0;

	head_td->pTDInfo->skb = skb;

	priv->iTDUsed[dma_idx]++;

	/* Take ownership */
	wmb();
	head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;

	/* get Next */
	wmb();
	priv->apCurrTD[dma_idx] = head_td->next;

	spin_unlock_irqrestore(&priv->lock, flags);

	vnt_generate_fifo_header(priv, dma_idx, head_td, skb);

	if (MACbIsRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
		MACbPSWakeup(priv->PortOffset);

	spin_lock_irqsave(&priv->lock, flags);

	priv->bPWBitOn = false;

	/* Set TSR1 & ReqCount in TxDescHead */
	head_td->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
	head_td->m_td1TD1.wReqCount =
			cpu_to_le16((u16)head_td->pTDInfo->dwReqCount);

	head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);

	if (dma_idx == TYPE_AC0DMA) {
		head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;

		MACvTransmitAC0(priv->PortOffset);
	} else {
		MACvTransmit0(priv->PortOffset);
	}

	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}
Example #22
0
/*should call before software enc*/
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	u16 fc = le16_to_cpu(hdr->frame_control);
	u16 ether_type;
	u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
	const struct iphdr *ip;

	if (!ieee80211_is_data(fc))
		goto end;

	if (ieee80211_is_nullfunc(fc))
		return true;

	ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
			      SNAP_SIZE + PROTOC_TYPE_SIZE);
	ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
	ether_type = ntohs(ether_type);

	if (ETH_P_IP == ether_type) {
		if (IPPROTO_UDP == ip->protocol) {
			struct udphdr *udp = (struct udphdr *)((u8 *) ip +
							       (ip->ihl << 2));
			if (((((u8 *) udp)[1] == 68) &&
			     (((u8 *) udp)[3] == 67)) ||
			    ((((u8 *) udp)[1] == 67) &&
			     (((u8 *) udp)[3] == 68))) {
				/*
				 * 68 : UDP BOOTP client
				 * 67 : UDP BOOTP server
				 */
				RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
					 DBG_DMESG, ("dhcp %s !!\n",
						     (is_tx) ? "Tx" : "Rx"));

				if (is_tx) {
					rtl_lps_leave(hw);
					ppsc->last_delaylps_stamp_jiffies =
					    jiffies;
				}

				return true;
			}
		}
	} else if (ETH_P_ARP == ether_type) {
		if (is_tx) {
			rtl_lps_leave(hw);
			ppsc->last_delaylps_stamp_jiffies = jiffies;
		}

		return true;
	} else if (ETH_P_PAE == ether_type) {
		RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
			 ("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"));

		if (is_tx) {
			rtl_lps_leave(hw);
			ppsc->last_delaylps_stamp_jiffies = jiffies;
		}

		return true;
	} else if (0x86DD == ether_type) {
		return true;
	}

end:
	return false;
}
Example #23
0
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	struct ieee80211_rate *txrate;
	u16 fc = le16_to_cpu(hdr->frame_control);

	memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc));

	if (ieee80211_is_data(fc)) {
		txrate = ieee80211_get_tx_rate(hw, info);
		tcb_desc->hw_rate = txrate->hw_value;

		/*
		 *we set data rate RTL_RC_CCK_RATE1M
		 *in rtl_rc.c   if skb is special data or
		 *mgt which need low data rate.
		 */

		/*
		 *So tcb_desc->hw_rate is just used for
		 *special data and mgt frames
		 */
		if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = 7;

			tcb_desc->hw_rate =
			    rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
			tcb_desc->disable_ratefallback = 1;
		} else {
			/*
			 *because hw will nerver use hw_rate
			 *when tcb_desc->use_driver_rate = false
			 *so we never set highest N rate here,
			 *and N rate will all be controled by FW
			 *when tcb_desc->use_driver_rate = false
			 */
			if (rtlmac->ht_enable) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->b_multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->b_broadcast = 1;

		_rtl_txrate_selectmode(hw, tcb_desc);
		_rtl_query_bandwidth_mode(hw, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = 7;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;

		tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
	}
}
Example #24
0
static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
				    struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u8 *rxdesc = skb->data;
	struct ieee80211_hdr *hdr;
	bool unicast = false;
	__le16 fc;
	struct ieee80211_rx_status rx_status = {0};
	struct rtl_stats stats = {
		.signal = 0,
		.noise = -98,
		.rate = 0,
	};

	skb_pull(skb, RTL_RX_DESC_SIZE);
	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
	hdr = (struct ieee80211_hdr *)(skb->data);
	fc = hdr->frame_control;
	if (!stats.crc) {
		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));

		if (is_broadcast_ether_addr(hdr->addr1)) {
			/*TODO*/;
		} else if (is_multicast_ether_addr(hdr->addr1)) {
			/*TODO*/
		} else {
			unicast = true;
			rtlpriv->stats.rxbytesunicast +=  skb->len;
		}

		rtl_is_special_data(hw, skb, false);

		if (ieee80211_is_data(fc)) {
			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);

			if (unicast)
				rtlpriv->link_info.num_rx_inperiod++;
		}
	}
}

static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
				      struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u8 *rxdesc = skb->data;
	struct ieee80211_hdr *hdr;
	bool unicast = false;
	__le16 fc;
	struct ieee80211_rx_status rx_status = {0};
	struct rtl_stats stats = {
		.signal = 0,
		.noise = -98,
		.rate = 0,
	};

	skb_pull(skb, RTL_RX_DESC_SIZE);
	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
	hdr = (struct ieee80211_hdr *)(skb->data);
	fc = hdr->frame_control;
	if (!stats.crc) {
		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));

		if (is_broadcast_ether_addr(hdr->addr1)) {
			/*TODO*/;
		} else if (is_multicast_ether_addr(hdr->addr1)) {
			/*TODO*/
		} else {
			unicast = true;
			rtlpriv->stats.rxbytesunicast +=  skb->len;
		}

		rtl_is_special_data(hw, skb, false);

		if (ieee80211_is_data(fc)) {
			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);

			if (unicast)
				rtlpriv->link_info.num_rx_inperiod++;
		}
		if (likely(rtl_action_proc(hw, skb, false))) {
			struct sk_buff *uskb = NULL;
			u8 *pdata;

			uskb = dev_alloc_skb(skb->len + 128);
			if (uskb) {	/* drop packet on allocation failure */
				memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
				       sizeof(rx_status));
				pdata = (u8 *)skb_put(uskb, skb->len);
				memcpy(pdata, skb->data, skb->len);
				ieee80211_rx_irqsafe(hw, uskb);
			}
			dev_kfree_skb_any(skb);
		} else {
			dev_kfree_skb_any(skb);
		}
	}
}

static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct sk_buff *_skb;
	struct sk_buff_head rx_queue;
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	skb_queue_head_init(&rx_queue);
	if (rtlusb->usb_rx_segregate_hdl)
		rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue);
	WARN_ON(skb_queue_empty(&rx_queue));
	while (!skb_queue_empty(&rx_queue)) {
		_skb = skb_dequeue(&rx_queue);
		_rtl_usb_rx_process_agg(hw, skb);
		ieee80211_rx_irqsafe(hw, skb);
	}
}

static void _rtl_rx_completed(struct urb *_urb)
{
	struct sk_buff *skb = (struct sk_buff *)_urb->context;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0];
	struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	int err = 0;

	if (unlikely(IS_USB_STOP(rtlusb)))
		goto free;

	if (likely(0 == _urb->status)) {
		/* If this code were moved to work queue, would CPU
		 * utilization be improved?  NOTE: We shall allocate another skb
		 * and reuse the original one.
		 */
		skb_put(skb, _urb->actual_length);

		if (likely(!rtlusb->usb_rx_segregate_hdl)) {
			struct sk_buff *_skb;
			_rtl_usb_rx_process_noagg(hw, skb);
			_skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC);
			if (IS_ERR(_skb)) {
				err = PTR_ERR(_skb);
				RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
					 "Can't allocate skb for bulk IN!\n");
				return;
			}
			skb = _skb;
		} else{
			/* TO DO */
			_rtl_rx_pre_process(hw, skb);
			pr_err("rx agg not supported\n");
		}
		goto resubmit;
	}

	switch (_urb->status) {
	/* disconnect */
	case -ENOENT:
	case -ECONNRESET:
	case -ENODEV:
	case -ESHUTDOWN:
		goto free;
	default:
		break;
	}

resubmit:
	skb_reset_tail_pointer(skb);
	skb_trim(skb, 0);

	usb_anchor_urb(_urb, &rtlusb->rx_submitted);
	err = usb_submit_urb(_urb, GFP_ATOMIC);
	if (unlikely(err)) {
		usb_unanchor_urb(_urb);
		goto free;
	}
	return;

free:
	dev_kfree_skb_irq(skb);
}

static int _rtl_usb_receive(struct ieee80211_hw *hw)
{
	struct urb *urb;
	struct sk_buff *skb;
	int err;
	int i;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	WARN_ON(0 == rtlusb->rx_urb_num);
	/* 1600 == 1514 + max WLAN header + rtk info */
	WARN_ON(rtlusb->rx_max_size < 1600);

	for (i = 0; i < rtlusb->rx_urb_num; i++) {
		err = -ENOMEM;
		urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!urb) {
			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
				 "Failed to alloc URB!!\n");
			goto err_out;
		}

		skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
		if (IS_ERR(skb)) {
			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
				 "Failed to prep_rx_urb!!\n");
			err = PTR_ERR(skb);
			goto err_out;
		}

		usb_anchor_urb(urb, &rtlusb->rx_submitted);
		err = usb_submit_urb(urb, GFP_KERNEL);
		if (err)
			goto err_out;
		usb_free_urb(urb);
	}
	return 0;

err_out:
	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
	return err;
}

static int rtl_usb_start(struct ieee80211_hw *hw)
{
	int err;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	err = rtlpriv->cfg->ops->hw_init(hw);
	if (!err) {
		rtl_init_rx_config(hw);

		/* Enable software */
		SET_USB_START(rtlusb);
		/* should after adapter start and interrupt enable. */
		set_hal_start(rtlhal);

		/* Start bulk IN */
		_rtl_usb_receive(hw);
	}

	return err;
}
/**
 *
 *
 */

/*=======================  tx =========================================*/
static void rtl_usb_cleanup(struct ieee80211_hw *hw)
{
	u32 i;
	struct sk_buff *_skb;
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
	struct ieee80211_tx_info *txinfo;

	SET_USB_STOP(rtlusb);

	/* clean up rx stuff. */
	usb_kill_anchored_urbs(&rtlusb->rx_submitted);

	/* clean up tx stuff */
	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
		while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) {
			rtlusb->usb_tx_cleanup(hw, _skb);
			txinfo = IEEE80211_SKB_CB(_skb);
			ieee80211_tx_info_clear_status(txinfo);
			txinfo->flags |= IEEE80211_TX_STAT_ACK;
			ieee80211_tx_status_irqsafe(hw, _skb);
		}
		usb_kill_anchored_urbs(&rtlusb->tx_pending[i]);
	}
	usb_kill_anchored_urbs(&rtlusb->tx_submitted);
}
Example #25
0
/* Assumes you've already done the endian to CPU conversion */
bool ath9k_cmn_rx_accept(struct ath_common *common,
			 struct ieee80211_hdr *hdr,
			 struct ieee80211_rx_status *rxs,
			 struct ath_rx_status *rx_stats,
			 bool *decrypt_error,
			 unsigned int rxfilter)
{
	struct ath_hw *ah = common->ah;
	bool is_mc, is_valid_tkip, strip_mic, mic_error;
	__le16 fc;

	fc = hdr->frame_control;

	is_mc = !!is_multicast_ether_addr(hdr->addr1);
	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
	strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
		ieee80211_has_protected(fc) &&
		!(rx_stats->rs_status &
		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
		 ATH9K_RXERR_KEYMISS));

	/*
	 * Key miss events are only relevant for pairwise keys where the
	 * descriptor does contain a valid key index. This has been observed
	 * mostly with CCMP encryption.
	 */
	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;

	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
		!ieee80211_has_morefrags(fc) &&
		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
		(rx_stats->rs_status & ATH9K_RXERR_MIC);

	/*
	 * The rx_stats->rs_status will not be set until the end of the
	 * chained descriptors so it can be ignored if rs_more is set. The
	 * rs_more will be false at the last element of the chained
	 * descriptors.
	 */
	if (rx_stats->rs_status != 0) {
		u8 status_mask;

		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
			mic_error = false;
		}

		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
			*decrypt_error = true;
			mic_error = false;
		}


		/*
		 * Reject error frames with the exception of
		 * decryption and MIC failures. For monitor mode,
		 * we also ignore the CRC error.
		 */
		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
			      ATH9K_RXERR_KEYMISS;

		if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
			status_mask |= ATH9K_RXERR_CRC;

		if (rx_stats->rs_status & ~status_mask)
			return false;
	}

	/*
	 * For unicast frames the MIC error bit can have false positives,
	 * so all MIC error reports need to be validated in software.
	 * False negatives are not common, so skip software verification
	 * if the hardware considers the MIC valid.
	 */
	if (strip_mic)
		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
	else if (is_mc && mic_error)
		rxs->flag |= RX_FLAG_MMIC_ERROR;

	return true;
}
Example #26
0
/*should call before software enc*/
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	__le16 fc = rtl_get_fc(skb);
	u16 ether_type;
	u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
	const struct iphdr *ip;

	if (!ieee80211_is_data(fc))
		return false;


	ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
			      SNAP_SIZE + PROTOC_TYPE_SIZE);
	ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
	/*	ether_type = ntohs(ether_type); */

	if (ETH_P_IP == ether_type) {
		if (IPPROTO_UDP == ip->protocol) {
			struct udphdr *udp = (struct udphdr *)((u8 *) ip +
							       (ip->ihl << 2));
			if (((((u8 *) udp)[1] == 68) &&
			     (((u8 *) udp)[3] == 67)) ||
			    ((((u8 *) udp)[1] == 67) &&
			     (((u8 *) udp)[3] == 68))) {
				/*
				 * 68 : UDP BOOTP client
				 * 67 : UDP BOOTP server
				 */
				RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
					 DBG_DMESG, "dhcp %s !!\n",
					 is_tx ? "Tx" : "Rx");

				if (is_tx) {
					schedule_work(&rtlpriv->
						      works.lps_leave_work);
					ppsc->last_delaylps_stamp_jiffies =
					    jiffies;
				}

				return true;
			}
		}
	} else if (ETH_P_ARP == ether_type) {
		if (is_tx) {
			schedule_work(&rtlpriv->works.lps_leave_work);
			ppsc->last_delaylps_stamp_jiffies = jiffies;
		}

		return true;
	} else if (ETH_P_PAE == ether_type) {
		RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
			 "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");

		if (is_tx) {
			schedule_work(&rtlpriv->works.lps_leave_work);
			ppsc->last_delaylps_stamp_jiffies = jiffies;
		}

		return true;
	} else if (ETH_P_IPV6 == ether_type) {
		/* IPv6 */
		return true;
	}

	return false;
}
Example #27
0
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct ieee80211_sta *sta,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	struct ieee80211_rate *txrate;
	__le16 fc = hdr->frame_control;

	txrate = ieee80211_get_tx_rate(hw, info);
	if (txrate)
		tcb_desc->hw_rate = txrate->hw_value;
	else
		tcb_desc->hw_rate = 0;

	if (ieee80211_is_data(fc)) {
		/*
		 *we set data rate INX 0
		 *in rtl_rc.c   if skb is special data or
		 *mgt which need low data rate.
		 */

		/*
		 *So tcb_desc->hw_rate is just used for
		 *special data and mgt frames
		 */
		if (info->control.rates[0].idx == 0 ||
				ieee80211_is_nullfunc(fc)) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;

			tcb_desc->disable_ratefallback = 1;
		} else {
			/*
			 *because hw will nerver use hw_rate
			 *when tcb_desc->use_driver_rate = false
			 *so we never set highest N rate here,
			 *and N rate will all be controlled by FW
			 *when tcb_desc->use_driver_rate = false
			 */
			if (sta && (sta->ht_cap.ht_supported)) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->broadcast = 1;

		_rtl_txrate_selectmode(hw, sta, tcb_desc);
		_rtl_query_bandwidth_mode(hw, sta, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, sta, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;
		tcb_desc->packet_bw = false;
	}
}
Example #28
0
static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct rtl8192_tx_ring *ring;
	struct rtl_tx_desc *pdesc;
	u8 idx;
	unsigned int queue_index, hw_queue;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	__le16 fc = hdr->frame_control;
	u8 *pda_addr = hdr->addr1;
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	/*ssn */
	u8 *qc = NULL;
	u8 tid = 0;
	u16 seq_number = 0;
	u8 own;
	u8 temp_one = 1;

	if (ieee80211_is_mgmt(fc))
		rtl_tx_mgmt_proc(hw, skb);
	rtl_action_proc(hw, skb, true);

	queue_index = skb_get_queue_mapping(skb);
	hw_queue = _rtl_mac_to_hwqueue(fc, queue_index);

	if (is_multicast_ether_addr(pda_addr))
		rtlpriv->stats.txbytesmulticast += skb->len;
	else if (is_broadcast_ether_addr(pda_addr))
		rtlpriv->stats.txbytesbroadcast += skb->len;
	else
		rtlpriv->stats.txbytesunicast += skb->len;

	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);

	ring = &rtlpci->tx_ring[hw_queue];
	if (hw_queue != BEACON_QUEUE)
		idx = (ring->idx + skb_queue_len(&ring->queue)) %
				ring->entries;
	else
		idx = 0;

	pdesc = &ring->desc[idx];
	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
			true, HW_DESC_OWN);

	if ((own == 1) && (hw_queue != BEACON_QUEUE)) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
			 ("No more TX desc@%d, ring->idx = %d,"
			  "idx = %d, skb_queue_len = 0x%d\n",
			  hw_queue, ring->idx, idx,
			  skb_queue_len(&ring->queue)));

		spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
		return skb->len;
	}

	/*
	 *if(ieee80211_is_nullfunc(fc)) {
	 *      spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
	 *      return 1;
	 *}
	 */

	if (ieee80211_is_data_qos(fc)) {
		qc = ieee80211_get_qos_ctl(hdr);
		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;

		seq_number = mac->tids[tid].seq_number;
		seq_number &= IEEE80211_SCTL_SEQ;
		/*
		 *hdr->seq_ctrl = hdr->seq_ctrl &
		 *cpu_to_le16(IEEE80211_SCTL_FRAG);
		 *hdr->seq_ctrl |= cpu_to_le16(seq_number);
		 */

		seq_number += 1;
	}

	if (ieee80211_is_data(fc))
		rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX);

	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc,
					info, skb, hw_queue);

	__skb_queue_tail(&ring->queue, skb);

	rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true,
				    HW_DESC_OWN, (u8 *)&temp_one);

	if (!ieee80211_has_morefrags(hdr->frame_control)) {
		if (qc)
			mac->tids[tid].seq_number = seq_number;
	}

	if ((ring->entries - skb_queue_len(&ring->queue)) < 2 &&
	    hw_queue != BEACON_QUEUE) {

		RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
			 ("less desc left, stop skb_queue@%d, "
			  "ring->idx = %d,"
			  "idx = %d, skb_queue_len = 0x%d\n",
			  hw_queue, ring->idx, idx,
			  skb_queue_len(&ring->queue)));

		ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
	}

	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);

	rtlpriv->cfg->ops->tx_polling(hw, hw_queue);

	return 0;
}
Example #29
0
static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	int rx_queue_idx = RTL_PCI_RX_MPDU_QUEUE;

	struct ieee80211_rx_status rx_status = { 0 };
	unsigned int count = rtlpci->rxringcount;
	u8 own;
	u8 tmp_one;
	u32 bufferaddress;
	bool unicast = false;

	struct rtl_stats stats = {
		.signal = 0,
		.noise = -98,
		.rate = 0,
	};

	/*RX NORMAL PKT */
	while (count--) {
		/*rx descriptor */
		struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
				rtlpci->rx_ring[rx_queue_idx].idx];
		/*rx pkt */
		struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
				rtlpci->rx_ring[rx_queue_idx].idx];

		own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
						       false, HW_DESC_OWN);

		if (own) {
			/*wait data to be filled by hardware */
			return;
		} else {
			struct ieee80211_hdr *hdr;
			__le16 fc;
			struct sk_buff *new_skb = NULL;

			rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
							 &rx_status,
							 (u8 *) pdesc, skb);

			pci_unmap_single(rtlpci->pdev,
					 *((dma_addr_t *) skb->cb),
					 rtlpci->rxbuffersize,
					 PCI_DMA_FROMDEVICE);

			skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
							 false,
							 HW_DESC_RXPKT_LEN));
			skb_reserve(skb,
				    stats.rx_drvinfo_size + stats.rx_bufshift);

			/*
			 *NOTICE This can not be use for mac80211,
			 *this is done in mac80211 code,
			 *if you done here sec DHCP will fail
			 *skb_trim(skb, skb->len - 4);
			 */

			hdr = (struct ieee80211_hdr *)(skb->data);
			fc = hdr->frame_control;

			if (!stats.crc) {
				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
				       sizeof(rx_status));

				if (is_broadcast_ether_addr(hdr->addr1))
					;/*TODO*/
				else {
					if (is_multicast_ether_addr(hdr->addr1))
						;/*TODO*/
					else {
						unicast = true;
						rtlpriv->stats.rxbytesunicast +=
						    skb->len;
					}
				}

				rtl_is_special_data(hw, skb, false);

				if (ieee80211_is_data(fc)) {
					rtlpriv->cfg->ops->led_control(hw,
							       LED_CTL_RX);

					if (unicast)
						rtlpriv->link_info.
						    num_rx_inperiod++;
				}

				if (unlikely(!rtl_action_proc(hw, skb,
				    false))) {
					dev_kfree_skb_any(skb);
				} else {
					struct sk_buff *uskb = NULL;
					u8 *pdata;
					uskb = dev_alloc_skb(skb->len + 128);
					if (!uskb) {
						RT_TRACE(rtlpriv,
							(COMP_INTR | COMP_RECV),
							DBG_EMERG,
							("can't alloc rx skb\n"));
						goto done;
					}
					memcpy(IEEE80211_SKB_RXCB(uskb),
							&rx_status,
							sizeof(rx_status));
					pdata = (u8 *)skb_put(uskb, skb->len);
					memcpy(pdata, skb->data, skb->len);
					dev_kfree_skb_any(skb);

					ieee80211_rx_irqsafe(hw, uskb);
				}
			} else {
				dev_kfree_skb_any(skb);
			}

			if (((rtlpriv->link_info.num_rx_inperiod +
				rtlpriv->link_info.num_tx_inperiod) > 8) ||
				(rtlpriv->link_info.num_rx_inperiod > 2)) {
				rtl_lps_leave(hw);
			}

			new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
			if (unlikely(!new_skb)) {
				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
					 DBG_EMERG,
					 ("can't alloc skb for rx\n"));
				goto done;
			}
			skb = new_skb;
			/*skb->dev = dev; */

			rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
							     rx_ring
							     [rx_queue_idx].
							     idx] = skb;
			*((dma_addr_t *) skb->cb) =
			    pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
					   rtlpci->rxbuffersize,
					   PCI_DMA_FROMDEVICE);

		}
done:
		bufferaddress = (u32)(*((dma_addr_t *) skb->cb));
		tmp_one = 1;
		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
					    HW_DESC_RXBUFF_ADDR,
					    (u8 *)&bufferaddress);
		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
					    (u8 *)&tmp_one);
		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
					    HW_DESC_RXPKT_LEN,
					    (u8 *)&rtlpci->rxbuffersize);

		if (rtlpci->rx_ring[rx_queue_idx].idx ==
		    rtlpci->rxringcount - 1)
			rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
						    HW_DESC_RXERO,
						    (u8 *)&tmp_one);

		rtlpci->rx_ring[rx_queue_idx].idx =
		    (rtlpci->rx_ring[rx_queue_idx].idx + 1) %
		    rtlpci->rxringcount;
	}

}

static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
{
	struct ieee80211_hw *hw = dev_id;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	unsigned long flags;
	u32 inta = 0;
	u32 intb = 0;

	if (rtlpci->irq_enabled == 0)
		return IRQ_HANDLED;

	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);

	/*read ISR: 4/8bytes */
	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);

	/*Shared IRQ or HW disappared */
	if (!inta || inta == 0xffff)
		goto done;

	/*<1> beacon related */
	if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("beacon ok interrupt!\n"));
	}

	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER])) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("beacon err interrupt!\n"));
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("beacon interrupt!\n"));
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_BcnInt]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("prepare beacon for interrupt!\n"));
		tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet);
	}

	/*<3> Tx related */
	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TXFOVW]))
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("IMR_TXFOVW!\n"));

	if (inta & rtlpriv->cfg->maps[RTL_IMR_MGNTDOK]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("Manage ok interrupt!\n"));
		_rtl_pci_tx_isr(hw, MGNT_QUEUE);
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_HIGHDOK]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("HIGH_QUEUE ok interrupt!\n"));
		_rtl_pci_tx_isr(hw, HIGH_QUEUE);
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_BKDOK]) {
		rtlpriv->link_info.num_tx_inperiod++;

		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("BK Tx OK interrupt!\n"));
		_rtl_pci_tx_isr(hw, BK_QUEUE);
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_BEDOK]) {
		rtlpriv->link_info.num_tx_inperiod++;

		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("BE TX OK interrupt!\n"));
		_rtl_pci_tx_isr(hw, BE_QUEUE);
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_VIDOK]) {
		rtlpriv->link_info.num_tx_inperiod++;

		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("VI TX OK interrupt!\n"));
		_rtl_pci_tx_isr(hw, VI_QUEUE);
	}

	if (inta & rtlpriv->cfg->maps[RTL_IMR_VODOK]) {
		rtlpriv->link_info.num_tx_inperiod++;

		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
			 ("Vo TX OK interrupt!\n"));
		_rtl_pci_tx_isr(hw, VO_QUEUE);
	}

	/*<2> Rx related */
	if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) {
		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n"));
		tasklet_schedule(&rtlpriv->works.irq_tasklet);
	}

	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
			 ("rx descriptor unavailable!\n"));
		tasklet_schedule(&rtlpriv->works.irq_tasklet);
	}

	if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n"));
		tasklet_schedule(&rtlpriv->works.irq_tasklet);
	}

	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
	return IRQ_HANDLED;

done:
	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
	return IRQ_HANDLED;
}

static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
{
	_rtl_pci_rx_interrupt(hw);
}
Example #30
0
/* hard_start_xmit function for master radio interface wifi#.
 * AP processing (TX rate control, power save buffering, etc.).
 * Use hardware TX function to send the frame. */
netdev_tx_t hostap_master_start_xmit(struct sk_buff *skb,
				     struct net_device *dev)
{
	struct hostap_interface *iface;
	local_info_t *local;
	netdev_tx_t ret = NETDEV_TX_BUSY;
	u16 fc;
	struct hostap_tx_data tx;
	ap_tx_ret tx_ret;
	struct hostap_skb_tx_data *meta;
	int no_encrypt = 0;
	struct ieee80211_hdr *hdr;

	iface = netdev_priv(dev);
	local = iface->local;

	tx.skb = skb;
	tx.sta_ptr = NULL;

	meta = (struct hostap_skb_tx_data *) skb->cb;
	if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
		printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
		       "expected 0x%08x)\n",
		       dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);
		ret = NETDEV_TX_OK;
		iface->stats.tx_dropped++;
		goto fail;
	}

	if (local->host_encrypt) {
		/* Set crypt to default algorithm and key; will be replaced in
		 * AP code if STA has own alg/key */
		tx.crypt = local->crypt_info.crypt[local->crypt_info.tx_keyidx];
		tx.host_encrypt = 1;
	} else {
		tx.crypt = NULL;
		tx.host_encrypt = 0;
	}

	if (skb->len < 24) {
		printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
		       "(len=%d)\n", dev->name, skb->len);
		ret = NETDEV_TX_OK;
		iface->stats.tx_dropped++;
		goto fail;
	}

	/* FIX (?):
	 * Wi-Fi 802.11b test plan suggests that AP should ignore power save
	 * bit in authentication and (re)association frames and assume tha
	 * STA remains awake for the response. */
	tx_ret = hostap_handle_sta_tx(local, &tx);
	skb = tx.skb;
	meta = (struct hostap_skb_tx_data *) skb->cb;
	hdr = (struct ieee80211_hdr *) skb->data;
	fc = le16_to_cpu(hdr->frame_control);
	switch (tx_ret) {
	case AP_TX_CONTINUE:
		break;
	case AP_TX_CONTINUE_NOT_AUTHORIZED:
		if (local->ieee_802_1x &&
		    ieee80211_is_data(hdr->frame_control) &&
		    meta->ethertype != ETH_P_PAE &&
		    !(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
			printk(KERN_DEBUG "%s: dropped frame to unauthorized "
			       "port (IEEE 802.1X): ethertype=0x%04x\n",
			       dev->name, meta->ethertype);
			hostap_dump_tx_80211(dev->name, skb);

			ret = NETDEV_TX_OK; /* drop packet */
			iface->stats.tx_dropped++;
			goto fail;
		}
		break;
	case AP_TX_DROP:
		ret = NETDEV_TX_OK; /* drop packet */
		iface->stats.tx_dropped++;
		goto fail;
	case AP_TX_RETRY:
		goto fail;
	case AP_TX_BUFFERED:
		/* do not free skb here, it will be freed when the
		 * buffered frame is sent/timed out */
		ret = NETDEV_TX_OK;
		goto tx_exit;
	}

	/* Request TX callback if protocol version is 2 in 802.11 header;
	 * this version 2 is a special case used between hostapd and kernel
	 * driver */
	if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) &&
	    local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) {
		meta->tx_cb_idx = local->ap->tx_callback_idx;

		/* remove special version from the frame header */
		fc &= ~IEEE80211_FCTL_VERS;
		hdr->frame_control = cpu_to_le16(fc);
	}

	if (!ieee80211_is_data(hdr->frame_control)) {
		no_encrypt = 1;
		tx.crypt = NULL;
	}

	if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
	    !(fc & IEEE80211_FCTL_PROTECTED)) {
		no_encrypt = 1;
		PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
		       "unencrypted EAPOL frame\n", dev->name);
		tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */
	}

	if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
		tx.crypt = NULL;
	else if ((tx.crypt ||
		 local->crypt_info.crypt[local->crypt_info.tx_keyidx]) &&
		 !no_encrypt) {
		/* Add ISWEP flag both for firmware and host based encryption
		 */
		fc |= IEEE80211_FCTL_PROTECTED;
		hdr->frame_control = cpu_to_le16(fc);
	} else if (local->drop_unencrypted &&
		   ieee80211_is_data(hdr->frame_control) &&
		   meta->ethertype != ETH_P_PAE) {
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: dropped unencrypted TX data "
			       "frame (drop_unencrypted=1)\n", dev->name);
		}
		iface->stats.tx_dropped++;
		ret = NETDEV_TX_OK;
		goto fail;
	}

	if (tx.crypt) {
		skb = hostap_tx_encrypt(skb, tx.crypt);
		if (skb == NULL) {
			printk(KERN_DEBUG "%s: TX - encryption failed\n",
			       dev->name);
			ret = NETDEV_TX_OK;
			goto fail;
		}
		meta = (struct hostap_skb_tx_data *) skb->cb;
		if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
			printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
			       "expected 0x%08x) after hostap_tx_encrypt\n",
			       dev->name, meta->magic,
			       HOSTAP_SKB_TX_DATA_MAGIC);
			ret = NETDEV_TX_OK;
			iface->stats.tx_dropped++;
			goto fail;
		}
	}

	if (local->func->tx == NULL || local->func->tx(skb, dev)) {
		ret = NETDEV_TX_OK;
		iface->stats.tx_dropped++;
	} else {
		ret = NETDEV_TX_OK;
		iface->stats.tx_packets++;
		iface->stats.tx_bytes += skb->len;
	}

 fail:
	if (ret == NETDEV_TX_OK && skb)
		dev_kfree_skb(skb);
 tx_exit:
	if (tx.sta_ptr)
		hostap_handle_sta_release(tx.sta_ptr);
	return ret;
}