Example #1
0
static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
					struct ieee80211_hdr *hdr,
					u16 len,
					u32 ampdu_status,
					struct iwl_rx_mem_buffer *rxb,
					struct ieee80211_rx_status *stats)
{
	/* We only process data packets if the interface is open */
	if (unlikely(!priv->is_open)) {
		IWL_DEBUG_DROP_LIMIT(priv,
		    "Dropping packet while interface is not open.\n");
		return;
	}

	/* In case of HW accelerated crypto and bad decryption, drop */
	if (!priv->cfg->mod_params->sw_crypto &&
	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
		return;

	/* Resize SKB from mac header to end of packet */
	skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
	skb_put(rxb->skb, len);

	iwl_update_stats(priv, false, hdr->frame_control, len);
	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
	priv->alloc_rxb_skb--;
	rxb->skb = NULL;
}
Example #2
0
static void packet_came(struct ieee80211_hw *hw, char *pRxBufferAddress, int PacketSize)
{
	struct wbsoft_priv *priv = hw->priv;
	struct sk_buff *skb;
	struct ieee80211_rx_status rx_status = {0};

	if (!priv->enabled)
		return;

	skb = dev_alloc_skb(PacketSize);
	if (!skb) {
		printk("Not enough memory for packet, FIXME\n");
		return;
	}

	memcpy(skb_put(skb, PacketSize),
	       pRxBufferAddress,
	       PacketSize);

/*
	rx_status.rate = 10;
	rx_status.channel = 1;
	rx_status.freq = 12345;
	rx_status.phymode = MODE_IEEE80211B;
*/

	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
	ieee80211_rx_irqsafe(hw, skb);
}
static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
				   struct sk_buff *skb)
{
	struct mac80211_hwsim_data *data = hw->priv;
	int i, ack = 0;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_rx_status rx_status;

	memset(&rx_status, 0, sizeof(rx_status));
	/* TODO: set mactime */
	rx_status.freq = data->channel->center_freq;
	rx_status.band = data->channel->band;
	rx_status.rate_idx = info->tx_rate_idx;
	/* TODO: simulate signal strength (and optional packet drop) */

	/* Copy skb to all enabled radios that are on the current frequency */
	for (i = 0; i < hwsim_radio_count; i++) {
		struct mac80211_hwsim_data *data2;
		struct sk_buff *nskb;

		if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw)
			continue;
		data2 = hwsim_radios[i]->priv;
		if (!data2->started || !data2->radio_enabled ||
		    data->channel->center_freq != data2->channel->center_freq)
			continue;

		nskb = skb_copy(skb, GFP_ATOMIC);
		if (nskb == NULL)
			continue;

		if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr,
			   ETH_ALEN) == 0)
			ack = 1;
		ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status);
	}

	return ack;
}
Example #4
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 #5
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 #6
0
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;
	unsigned int header_length;
	int rate_idx;
	/*
	 * 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);

	/* Trim buffer to correct size */
	skb_trim(entry->skb, rxdesc.size);

	/*
	 * The data behind the ieee80211 header must be
	 * aligned on a 4 byte boundary.
	 */
	header_length = ieee80211_get_hdrlen_from_skb(entry->skb);

	/*
	 * Hardware might have stripped the IV/EIV/ICV data,
	 * in that case it is possible that the data was
	 * provided seperately (through hardware descriptor)
	 * in which case we should reinsert the data into the frame.
	 */
	if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
	    (rxdesc.flags & RX_FLAG_IV_STRIPPED))
		rt2x00crypto_rx_insert_iv(entry->skb, header_length,
					  &rxdesc);
	else if (rxdesc.dev_flags & RXDONE_L2PAD)
		rt2x00queue_remove_l2pad(entry->skb, header_length);
	else
		rt2x00queue_align_payload(entry->skb, header_length);

	/*
	 * Check if the frame was received using HT. In that case,
	 * the rate is the MCS index and should be passed to mac80211
	 * directly. Otherwise we need to translate the signal to
	 * the correct bitrate index.
	 */
	if (rxdesc.rate_mode == RATE_MODE_CCK ||
	    rxdesc.rate_mode == RATE_MODE_OFDM) {
		rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
	} else {
		rxdesc.flags |= RX_FLAG_HT;
		rate_idx = rxdesc.signal;
	}

	/*
	 * Update extra components
	 */
	rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
	rt2x00debug_update_crypto(rt2x00dev, &rxdesc);

	rx_status->mactime = rxdesc.timestamp;
	rx_status->rate_idx = rate_idx;
	rx_status->signal = rxdesc.rssi;
	rx_status->noise = rxdesc.noise;
	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);
	memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
	ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);

	/*
	 * Replace the skb with the freshly allocated one.
	 */
	entry->skb = skb;
	entry->flags = 0;

	rt2x00dev->ops->lib->clear_entry(entry);

	rt2x00queue_index_inc(entry->queue, Q_INDEX);
}
Example #7
0
int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	struct ieee80211_rx_status stats;
	const struct rx_status *status;
	struct sk_buff *skb;
	int bad_frame = 0;
	u16 fc;
	bool is_qos, is_4addr, need_padding;

	if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
	             FCS_LEN + sizeof(struct rx_status))
		return -EINVAL;

	memset(&stats, 0, sizeof(stats));

	/* Note about pass_failed_fcs and pass_ctrl access below:
	 * mac locking intentionally omitted here, as this is the only unlocked
	 * reader and the only writer is configure_filter. Plus, if there were
	 * any races accessing these variables, it wouldn't really matter.
	 * If mac80211 ever provides a way for us to access filter flags
	 * from outside configure_filter, we could improve on this. Also, this
	 * situation may change once we implement some kind of DMA-into-skb
	 * RX path. */

	/* Caller has to ensure that length >= sizeof(struct rx_status). */
	status = (struct rx_status *)
		(buffer + (length - sizeof(struct rx_status)));
	if (status->frame_status & ZD_RX_ERROR) {
		if (mac->pass_failed_fcs &&
				(status->frame_status & ZD_RX_CRC32_ERROR)) {
			stats.flag |= RX_FLAG_FAILED_FCS_CRC;
			bad_frame = 1;
		} else {
			return -EINVAL;
		}
	}

	stats.channel = _zd_chip_get_channel(&mac->chip);
	stats.freq = zd_channels[stats.channel - 1].freq;
	stats.phymode = MODE_IEEE80211G;
	stats.ssi = status->signal_strength;
	stats.signal = zd_rx_qual_percent(buffer,
		                          length - sizeof(struct rx_status),
		                          status);
	stats.rate = zd_rx_rate(buffer, status);

	length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
	buffer += ZD_PLCP_HEADER_SIZE;

	/* Except for bad frames, filter each frame to see if it is an ACK, in
	 * which case our internal TX tracking is updated. Normally we then
	 * bail here as there's no need to pass ACKs on up to the stack, but
	 * there is also the case where the stack has requested us to pass
	 * control frames on up (pass_ctrl) which we must consider. */
	if (!bad_frame &&
			filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
			&& !mac->pass_ctrl)
		return 0;

	fc = le16_to_cpu(*((__le16 *) buffer));

	is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
		 ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA);
	is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
		   (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
	need_padding = is_qos ^ is_4addr;

	skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
	if (skb == NULL)
		return -ENOMEM;
	if (need_padding) {
		/* Make sure the the payload data is 4 byte aligned. */
		skb_reserve(skb, 2);
	}

	memcpy(skb_put(skb, length), buffer, length);

	ieee80211_rx_irqsafe(hw, skb, &stats);
	return 0;
}
Example #8
0
File: dpc.c Project: 19Dan01/linux
static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb,
			u16 bytes_received)
{
	struct ieee80211_hw *hw = priv->hw;
	struct ieee80211_supported_band *sband;
	struct ieee80211_rx_status rx_status = { 0 };
	struct ieee80211_hdr *hdr;
	__le16 fc;
	u8 *rsr, *new_rsr, *rssi;
	__le64 *tsf_time;
	u16 frame_size;
	int ii, r;
	u8 *rx_sts, *rx_rate, *sq;
	u8 *skb_data;
	u8 rate_idx = 0;
	u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
	long rx_dbm;

	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
	frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2)));
	if (frame_size > 2346 || frame_size < 14) {
		dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n");
		return false;
	}

	skb_data = (u8 *)skb->data;

	rx_sts = skb_data;
	rx_rate = skb_data + 1;

	sband = hw->wiphy->bands[hw->conf.chandef.chan->band];

	for (r = RATE_1M; r < MAX_RATE; r++) {
		if (*rx_rate == rate[r])
			break;
	}

	priv->rx_rate = r;

	for (ii = 0; ii < sband->n_bitrates; ii++) {
		if (sband->bitrates[ii].hw_value == r) {
			rate_idx = ii;
				break;
		}
	}

	if (ii == sband->n_bitrates) {
		dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate);
		return false;
	}

	tsf_time = (__le64 *)(skb_data + bytes_received - 12);
	sq = skb_data + bytes_received - 4;
	new_rsr = skb_data + bytes_received - 3;
	rssi = skb_data + bytes_received - 2;
	rsr = skb_data + bytes_received - 1;
	if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
		return false;

	RFvRSSITodBm(priv, *rssi, &rx_dbm);

	priv->byBBPreEDRSSI = (u8)rx_dbm + 1;
	priv->uCurrRSSI = *rssi;

	skb_pull(skb, 4);
	skb_trim(skb, frame_size);

	rx_status.mactime = le64_to_cpu(*tsf_time);
	rx_status.band = hw->conf.chandef.chan->band;
	rx_status.signal = rx_dbm;
	rx_status.flag = 0;
	rx_status.freq = hw->conf.chandef.chan->center_freq;

	if (!(*rsr & RSR_CRCOK))
		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;

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

	rx_status.rate_idx = rate_idx;

	if (ieee80211_has_protected(fc)) {
		if (priv->byLocalID > REV_ID_VT3253_A1)
			rx_status.flag |= RX_FLAG_DECRYPTED;

		/* Drop packet */
		if (!(*new_rsr & NEWRSR_DECRYPTOK))
			return false;
	}

	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));

	ieee80211_rx_irqsafe(priv->hw, skb);

	return true;
}
Example #9
0
static void rtl8180_handle_rx(struct ieee80211_hw *dev)
{
	struct rtl8180_priv *priv = dev->priv;
	unsigned int count = 32;

	while (count--) {
		struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
		struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
		u32 flags = le32_to_cpu(entry->flags);

		if (flags & RTL818X_RX_DESC_FLAG_OWN)
			return;

		if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
				      RTL818X_RX_DESC_FLAG_FOF |
				      RTL818X_RX_DESC_FLAG_RX_ERR)))
			goto done;
		else {
			u32 flags2 = le32_to_cpu(entry->flags2);
			struct ieee80211_rx_status rx_status = {0};
			struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE);

			if (unlikely(!new_skb))
				goto done;

			pci_unmap_single(priv->pdev,
					 *((dma_addr_t *)skb->cb),
					 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
			skb_put(skb, flags & 0xFFF);

			rx_status.antenna = (flags2 >> 15) & 1;
			/* TODO: improve signal/rssi reporting */
			rx_status.qual = flags2 & 0xFF;
			rx_status.signal = (flags2 >> 8) & 0x7F;
			/* XXX: is this correct? */
			rx_status.rate_idx = (flags >> 20) & 0xF;
			rx_status.freq = dev->conf.channel->center_freq;
			rx_status.band = dev->conf.channel->band;
			rx_status.mactime = le64_to_cpu(entry->tsft);
			rx_status.flag |= RX_FLAG_TSFT;
			if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
				rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;

			ieee80211_rx_irqsafe(dev, skb, &rx_status);

			skb = new_skb;
			priv->rx_buf[priv->rx_idx] = skb;
			*((dma_addr_t *) skb->cb) =
				pci_map_single(priv->pdev, skb_tail_pointer(skb),
					       MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
		}

	done:
		entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
		entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
					   MAX_RX_SIZE);
		if (priv->rx_idx == 31)
			entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
		priv->rx_idx = (priv->rx_idx + 1) % 32;
	}
}
Example #10
0
/**
 * ethernic_recv(...): Recebe e trata pacotes 0x0808 recebidos da rede.
 */
int ethernic_recv_data (struct sk_buff *skb, struct net_device *dev, struct packet_type *pkt, 
						struct net_device *orig_dev)
{
	struct sk_buff *skb_recv=NULL;
	struct sk_buff *skb_recv_to_ieee80211rx=NULL;
	//struct sk_buff *skb_recv_1=NULL;
	//struct sk_buff *newskb=NULL;
	//struct sk_buff *_skb=NULL;
	//struct sk_buff *skb_recv_wlannic=NULL;
	struct ethhdr* eh=NULL;
	//static struct net_device *wifi_interf = NULL;
	//struct lvwnet_reg_omni_header* lh_reg_omni=NULL;
	//struct lvwnet_peers_info_header* lh_peers=NULL;
	//struct lvwnet_only_flag_header* lh_flag=NULL;
    //struct lvwnet_data_header* lh_data=NULL;
    //uint8_t* newdata = NULL;
    //uint8_t* _head = NULL;
    //uint8_t* _data = NULL;
    //uint8_t* _tail = NULL;
    //uint8_t* _end  = NULL;
    //int hdrlen = -1;
    //struct ieee80211_hdr *hdr80211 = NULL;
    //unsigned int _headlen = 0;
	//unsigned char *data1, *data2;    
	int len_data = -1;
	//int len_data_80211 = -1;
	//int len_2 = -1;
    
    qtd_msg_all++;
    //uint8_t radiotap[26];
    
	
	spin_lock(&lvwnet_lock);


	if( skb_mac_header_was_set(skb) ) {
            eh = eth_hdr(skb);
	} else {
            printk(KERN_ALERT "lvwnet_node: ---- ---- - - skb_mac_header NOT set!\n");
            goto ethernic_recv_out;
	}

	//printk (KERN_INFO "Frame from %pM, to %pM\n", eh->h_source, eh->h_dest);
    //normal node
	if (memcmp( dev->dev_addr, eh->h_dest, ETH_ALEN) != 0 ) {
            printk (KERN_ALERT "lvwnet_node: frame to other host. Device [%s] is in promiscuous mode? to: %pM, from: %pM.\n",
                    dev->name, eh->h_dest, eh->h_source);
            goto ethernic_recv_out;
	}
    //printk(KERN_ALERT "lvwnet_node: size of skb: %ld / %ld\n",sizeof(skb), sizeof(skb_recv));
	skb_recv = skb_copy(skb, GFP_ATOMIC);

	if (skb_recv == NULL){
            printk(KERN_ALERT "lvwnet_node: ERR -> skb_recv(2) == NULL\n");
            goto ethernic_recv_out;
	}

	//skb_reset_network_header(skb_recv);

    if (skb_recv->data == NULL) {
        printk(KERN_ALERT "lvwnet_node: received a NULL skb->data. [%s], line %d\n", __func__, __LINE__);
        goto ethernic_recv_out;
    }

	qtd_msg_data++;
	

	/*
	 * if (wifi_interf == NULL){
		wifi_interf = find_nic("wlan0");
		if (wifi_interf == NULL) {
			printk(KERN_ALERT "lvwnet_node: wireless interface (%s) not found! [%s:%d]\n", "wlan0", __func__, __LINE__);
			goto ethernic_recv_out;
		}
	}*/

	if (hw == NULL) {
		printk(KERN_ALERT "lvwnet_node: hw is NULL. Wireless NIC is present? (maybe not SoftMAC compatible...) [%s]\n", __func__);
	} else {
		if ( skb == NULL) {
			printk(KERN_ALERT "lvwnet_node: skb is NULL. [%s:%d]\n", __func__, __LINE__);
		} else {
			//skb->dev = wifi_interf;

			skb_recv_to_ieee80211rx = skb_copy(skb, GFP_ATOMIC);

			//skb_recv_1 = skb_pull(skb_recv_to_ieee80211rx, 1);
			skb_reset_network_header(skb_recv_to_ieee80211rx);
		

			
			len_data = skb_recv_to_ieee80211rx->len;

			if (skb_recv_to_ieee80211rx->data_len != 0) {
				printk(KERN_ALERT "lvwnet_node: data_len != 0. Non-linear skb here... [%s:%d]\n", __func__, __LINE__);
			}
			if (skb_is_nonlinear(skb_recv_to_ieee80211rx)) {
				printk(KERN_ALERT "lvwnet_node: skb_is_nonlinear returned true. Non-linear skb here... [%s:%d]\n", __func__, __LINE__);
			}
			if (skb_recv_to_ieee80211rx->data == NULL) {
				printk(KERN_ALERT "lvwnet_node: skb_recv_to_ieee80211rx->data == NULL. bad... [%s:%d]\n", __func__, __LINE__);
				goto ethernic_recv_out;
			}

			if (skb_recv_to_ieee80211rx != NULL){
				if (skb_recv_to_ieee80211rx->head != NULL){
					print_hex_dump(KERN_DEBUG, "0X0808 91(mac_head): ", DUMP_PREFIX_NONE,
									16, 1, (skb_recv_to_ieee80211rx->head + skb_recv_to_ieee80211rx->mac_header), 14, 0);
				}
			}
			printk(KERN_DEBUG ".................................................\n");

			if (skb_recv_to_ieee80211rx != NULL){
				if (skb_recv_to_ieee80211rx->data != NULL){
					print_hex_dump(KERN_DEBUG, "0X0808 92(data    ): ", DUMP_PREFIX_NONE,
								16, 1, skb_recv_to_ieee80211rx->data, len_data, 0);
				}
			}
			printk(KERN_DEBUG ".................................................\n");
			ieee80211_rx_irqsafe(hw, skb_recv_to_ieee80211rx);
		}
	}
	goto ethernic_recv_out;
 
ethernic_recv_out:
	dev_kfree_skb (skb);
	spin_unlock(&lvwnet_lock);

	//dev_kfree_skb (skb_recv_to_ieee80211rx);

	return 1;
}
Example #11
0
static void ar5523_data_rx_cb(struct urb *urb)
{
	struct ar5523_rx_data *data = urb->context;
	struct ar5523 *ar = data->ar;
	struct ar5523_rx_desc *desc;
	struct ar5523_chunk *chunk;
	struct ieee80211_hw *hw = ar->hw;
	struct ieee80211_rx_status *rx_status;
	u32 rxlen;
	int usblen = urb->actual_length;
	int hdrlen, pad;

	ar5523_dbg(ar, "%s\n", __func__);
	/* sync/async unlink faults aren't errors */
	if (urb->status) {
		if (urb->status != -ESHUTDOWN)
			ar5523_err(ar, "%s: USB err: %d\n", __func__,
				   urb->status);
		goto skip;
	}

	if (usblen < AR5523_MIN_RXBUFSZ) {
		ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen);
		goto skip;
	}

	chunk = (struct ar5523_chunk *) data->skb->data;

	if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) ||
		chunk->seqnum != 0) {
		ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n",
			   chunk->seqnum, chunk->flags,
			   be16_to_cpu(chunk->length));
		goto skip;
	}

	/* Rx descriptor is located at the end, 32-bit aligned */
	desc = (struct ar5523_rx_desc *)
		(data->skb->data + usblen - sizeof(struct ar5523_rx_desc));

	rxlen = be32_to_cpu(desc->len);
	if (rxlen > ar->rxbufsz) {
		ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n",
			   be32_to_cpu(desc->len));
		goto skip;
	}

	if (!rxlen) {
		ar5523_dbg(ar, "RX: rxlen is 0\n");
		goto skip;
	}

	if (be32_to_cpu(desc->status) != 0) {
		ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n",
			   be32_to_cpu(desc->status), be32_to_cpu(desc->len));
		goto skip;
	}

	skb_reserve(data->skb, sizeof(*chunk));
	skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc));

	hdrlen = ieee80211_get_hdrlen_from_skb(data->skb);
	if (!IS_ALIGNED(hdrlen, 4)) {
		ar5523_dbg(ar, "eek, alignment workaround activated\n");
		pad = ALIGN(hdrlen, 4) - hdrlen;
		memmove(data->skb->data + pad, data->skb->data, hdrlen);
		skb_pull(data->skb, pad);
		skb_put(data->skb, pad);
	}

	rx_status = IEEE80211_SKB_RXCB(data->skb);
	memset(rx_status, 0, sizeof(*rx_status));
	rx_status->freq = be32_to_cpu(desc->channel);
	rx_status->band = hw->conf.chandef.chan->band;
	rx_status->signal = -95 + be32_to_cpu(desc->rssi);

	ieee80211_rx_irqsafe(hw, data->skb);
	data->skb = NULL;

skip:
	if (data->skb) {
		dev_kfree_skb_irq(data->skb);
		data->skb = NULL;
	}

	ar5523_rx_data_put(ar, data);
	if (atomic_inc_return(&ar->rx_data_free_cnt) >=
	    AR5523_RX_DATA_REFILL_COUNT &&
	    test_bit(AR5523_HW_UP, &ar->flags))
		queue_work(ar->wq, &ar->rx_refill_work);
}
Example #12
0
File: dpc.c Project: 19Dan01/linux
int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
	unsigned long bytes_received)
{
	struct ieee80211_hw *hw = priv->hw;
	struct ieee80211_supported_band *sband;
	struct sk_buff *skb;
	struct ieee80211_rx_status rx_status = { 0 };
	struct ieee80211_hdr *hdr;
	__le16 fc;
	u8 *rsr, *new_rsr, *rssi, *frame;
	__le64 *tsf_time;
	u32 frame_size;
	int ii, r;
	u8 *rx_sts, *rx_rate, *sq, *sq_3;
	u32 wbk_status;
	u8 *skb_data;
	u16 *pay_load_len;
	u16 pay_load_with_padding;
	u8 rate_idx = 0;
	u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
	long rx_dbm;

	skb = ptr_rcb->skb;

	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
	wbk_status = *((u32 *)(skb->data));
	frame_size = wbk_status >> 16;
	frame_size += 4;

	if (bytes_received != frame_size) {
		dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n");
		return false;
	}

	if ((bytes_received > 2372) || (bytes_received <= 40)) {
		/* Frame Size error drop this packet.*/
		dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n");
		return false;
	}

	skb_data = (u8 *)skb->data;

	rx_sts = skb_data+4;
	rx_rate = skb_data+5;

	/* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */
	/* -8TSF - 4RSR - 4SQ3 - ?Padding */

	/* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */

	pay_load_len = (u16 *) (skb_data + 6);

	/*Fix hardware bug => PLCP_Length error */
	if (((bytes_received - (*pay_load_len)) > 27) ||
		((bytes_received - (*pay_load_len)) < 24) ||
			(bytes_received < (*pay_load_len))) {
		dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n",
							*pay_load_len);
		return false;
	}

	sband = hw->wiphy->bands[hw->conf.chandef.chan->band];

	for (r = RATE_1M; r < MAX_RATE; r++) {
		if (*rx_rate == rate[r])
			break;
	}

	priv->rx_rate = r;

	for (ii = 0; ii < sband->n_bitrates; ii++) {
		if (sband->bitrates[ii].hw_value == r) {
			rate_idx = ii;
				break;
		}
	}

	if (ii == sband->n_bitrates) {
		dev_dbg(&priv->usb->dev, "Wrong RxRate %x\n", *rx_rate);
		return false;
	}

	pay_load_with_padding = ((*pay_load_len / 4) +
		((*pay_load_len % 4) ? 1 : 0)) * 4;

	tsf_time = (__le64 *)(skb_data + 8 + pay_load_with_padding);

	priv->tsf_time = le64_to_cpu(*tsf_time);

	if (priv->bb_type == BB_TYPE_11G) {
		sq_3 = skb_data + 8 + pay_load_with_padding + 12;
		sq = sq_3;
	} else {
		sq = skb_data + 8 + pay_load_with_padding + 8;
		sq_3 = sq;
	}

	new_rsr = skb_data + 8 + pay_load_with_padding + 9;
	rssi = skb_data + 8 + pay_load_with_padding + 10;

	rsr = skb_data + 8 + pay_load_with_padding + 11;
	if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
		return false;

	frame_size = *pay_load_len;

	vnt_rf_rssi_to_dbm(priv, *rssi, &rx_dbm);

	priv->bb_pre_ed_rssi = (u8)rx_dbm + 1;
	priv->current_rssi = priv->bb_pre_ed_rssi;

	frame = skb_data + 8;

	skb_pull(skb, 8);
	skb_trim(skb, frame_size);

	rx_status.mactime = priv->tsf_time;
	rx_status.band = hw->conf.chandef.chan->band;
	rx_status.signal = rx_dbm;
	rx_status.flag = 0;
	rx_status.freq = hw->conf.chandef.chan->center_freq;

	if (!(*rsr & RSR_CRCOK))
		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;

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

	rx_status.rate_idx = rate_idx;

	if (ieee80211_has_protected(fc)) {
		if (priv->local_id > REV_ID_VT3253_A1) {
			rx_status.flag |= RX_FLAG_DECRYPTED;

			/* Drop packet */
			if (!(*new_rsr & NEWRSR_DECRYPTOK)) {
				dev_kfree_skb(skb);
				return true;
			}
		}
	}

	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));

	ieee80211_rx_irqsafe(priv->hw, skb);

	return true;
}
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);
}
Example #14
0
static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
{
	struct adm8211_priv *priv = dev->priv;
	unsigned int entry = priv->cur_rx % priv->rx_ring_size;
	u32 status;
	unsigned int pktlen;
	struct sk_buff *skb, *newskb;
	unsigned int limit = priv->rx_ring_size;
	u8 rssi, rate;

	while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
		if (!limit--)
			break;

		status = le32_to_cpu(priv->rx_ring[entry].status);
		rate = (status & RDES0_STATUS_RXDR) >> 12;
		rssi = le32_to_cpu(priv->rx_ring[entry].length) &
			RDES1_STATUS_RSSI;

		pktlen = status & RDES0_STATUS_FL;
		if (pktlen > RX_PKT_SIZE) {
			if (net_ratelimit())
				wiphy_debug(dev->wiphy, "frame too long (%d)\n",
					    pktlen);
			pktlen = RX_PKT_SIZE;
		}

		if (!priv->soft_rx_crc && status & RDES0_STATUS_ES) {
			skb = NULL; /* old buffer will be reused */
			/* TODO: update RX error stats */
			/* TODO: check RDES0_STATUS_CRC*E */
		} else if (pktlen < RX_COPY_BREAK) {
			skb = dev_alloc_skb(pktlen);
			if (skb) {
				pci_dma_sync_single_for_cpu(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					pktlen, PCI_DMA_FROMDEVICE);
				memcpy(skb_put(skb, pktlen),
				       skb_tail_pointer(priv->rx_buffers[entry].skb),
				       pktlen);
				pci_dma_sync_single_for_device(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
			}
		} else {
			newskb = dev_alloc_skb(RX_PKT_SIZE);
			if (newskb) {
				skb = priv->rx_buffers[entry].skb;
				skb_put(skb, pktlen);
				pci_unmap_single(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
				priv->rx_buffers[entry].skb = newskb;
				priv->rx_buffers[entry].mapping =
					pci_map_single(priv->pdev,
						       skb_tail_pointer(newskb),
						       RX_PKT_SIZE,
						       PCI_DMA_FROMDEVICE);
			} else {
				skb = NULL;
				/* TODO: update rx dropped stats */
			}

			priv->rx_ring[entry].buffer1 =
				cpu_to_le32(priv->rx_buffers[entry].mapping);
		}

		priv->rx_ring[entry].status = cpu_to_le32(RDES0_STATUS_OWN |
							  RDES0_STATUS_SQL);
		priv->rx_ring[entry].length =
			cpu_to_le32(RX_PKT_SIZE |
				    (entry == priv->rx_ring_size - 1 ?
				     RDES1_CONTROL_RER : 0));

		if (skb) {
			struct ieee80211_rx_status rx_status = {0};

			if (priv->pdev->revision < ADM8211_REV_CA)
				rx_status.signal = rssi;
			else
				rx_status.signal = 100 - rssi;

			rx_status.rate_idx = rate;

			rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
			rx_status.band = IEEE80211_BAND_2GHZ;

			memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
			ieee80211_rx_irqsafe(dev, skb);
		}

		entry = (++priv->cur_rx) % priv->rx_ring_size;
	}

	/* TODO: check LPC and update stats? */
}