Search Linux Wireless

[PATCH 5/6] adm8211: Improve TX path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Michael Wu <flamingice@xxxxxxxxxxxx>

This patch makes the TX path a little better.

Signed-off-by: Michael Wu <flamingice@xxxxxxxxxxxx>
---

 drivers/net/wireless/adm8211.c |   59 ++++++++++++++++++++++------------------
 drivers/net/wireless/adm8211.h |    6 ++--
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 4af3008..872b032 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -335,40 +335,44 @@ static int adm8211_get_tx_stats(struct ieee80211_hw *dev,
 static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
 {
 	struct adm8211_priv *priv = dev->priv;
-	unsigned dirty_tx;
+	unsigned int dirty_tx;
 
 	spin_lock(&priv->lock);
 
 	for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) {
-		unsigned entry = dirty_tx % priv->tx_ring_size;
+		unsigned int entry = dirty_tx % priv->tx_ring_size;
 		u32 status = le32_to_cpu(priv->tx_ring[entry].status);
+		struct adm8211_tx_ring_info *info;
+		struct sk_buff *skb;
 
 		if (status & TDES0_CONTROL_OWN ||
 		    !(status & TDES0_CONTROL_DONE))
 			break;
 
+		info = &priv->tx_buffers[entry];
+		skb = info->skb;
+
 		/* TODO: check TDES0_STATUS_TUF and TDES0_STATUS_TRO */
 
-		pci_unmap_single(priv->pdev, priv->tx_buffers[entry].mapping,
-				 priv->tx_buffers[entry].skb->len,
-				 PCI_DMA_TODEVICE);
+		pci_unmap_single(priv->pdev, info->mapping,
+				 info->skb->len, PCI_DMA_TODEVICE);
 
-		if (priv->tx_buffers[entry].tx_control.flags &
-		    IEEE80211_TXCTL_REQ_TX_STATUS) {
+		if (info->tx_control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) {
 			struct ieee80211_tx_status tx_status = {{0}};
 			struct ieee80211_hdr *hdr;
-			size_t hdrlen = ieee80211_get_hdrlen(le16_to_cpu(priv->tx_buffers[entry].hdr.frame_control));
-			hdr = (struct ieee80211_hdr *) skb_pull(priv->tx_buffers[entry].skb,
-								sizeof(struct adm8211_tx_hdr) - hdrlen);
-			memcpy(hdr, &priv->tx_buffers[entry].hdr, hdrlen);
-			memcpy(&tx_status.control, &priv->tx_buffers[entry].tx_control, sizeof(tx_status.control));
+			size_t hdrlen = info->hdrlen;
+
+			skb_pull(skb, sizeof(struct adm8211_tx_hdr));
+			hdr = (struct ieee80211_hdr *)skb_push(skb, hdrlen);
+			memcpy(hdr, skb->cb, hdrlen);
+			memcpy(&tx_status.control, &info->tx_control,
+			       sizeof(tx_status.control));
 			if (!(status & TDES0_STATUS_ES))
 				tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-			ieee80211_tx_status_irqsafe(dev, priv->tx_buffers[entry].skb,
-						    &tx_status);
+			ieee80211_tx_status_irqsafe(dev, skb, &tx_status);
 		} else
-			dev_kfree_skb_irq(priv->tx_buffers[entry].skb);
-		priv->tx_buffers[entry].skb = NULL;
+			dev_kfree_skb_irq(skb);
+		info->skb = NULL;
 	}
 
 	if (priv->cur_tx - dirty_tx < priv->tx_ring_size - 2)
@@ -384,7 +388,7 @@ 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 pktlen;
+	unsigned int pktlen;
 	struct sk_buff *skb, *newskb;
 	unsigned int limit = priv->rx_ring_size;
 	static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
@@ -1614,12 +1618,12 @@ static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int
 static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
 			   u16 plcp_signal,
 			   struct ieee80211_tx_control *control,
-			   struct ieee80211_hdr *hdr)
+			   size_t hdrlen)
 {
 	struct adm8211_priv *priv = dev->priv;
 	unsigned long flags;
 	dma_addr_t mapping;
-	unsigned entry;
+	unsigned int entry;
 	u32 flag;
 
 	mapping = pci_map_single(priv->pdev, skb->data, skb->len,
@@ -1640,7 +1644,7 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
 	priv->tx_buffers[entry].skb = skb;
 	priv->tx_buffers[entry].mapping = mapping;
 	memcpy(&priv->tx_buffers[entry].tx_control, control, sizeof(*control));
-	memcpy(&priv->tx_buffers[entry].hdr, hdr, sizeof(*hdr));
+	priv->tx_buffers[entry].hdrlen = hdrlen;
 	priv->tx_ring[entry].buffer1 = cpu_to_le32(mapping);
 
 	if (entry == priv->tx_ring_size - 1)
@@ -1667,7 +1671,7 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
 	u16 fc;
 	size_t payload_len, hdrlen;
 	int plcp, dur, len, plcp_signal, short_preamble;
-	struct ieee80211_hdr hdr;
+	struct ieee80211_hdr *hdr;
 
 	if (control->tx_rate < 0) {
 		short_preamble = 1;
@@ -1677,19 +1681,20 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
 		plcp_signal = control->tx_rate;
 	}
 
-	memcpy(&hdr, skb->data, sizeof(hdr));
-
-	fc = le16_to_cpu(hdr.frame_control) & ~IEEE80211_FCTL_PROTECTED;
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
 	hdrlen = ieee80211_get_hdrlen(fc);
+	memcpy(skb->cb, skb->data, hdrlen);
+	hdr = (struct ieee80211_hdr *)skb->cb;
 	skb_pull(skb, hdrlen);
 	payload_len = skb->len;
 
 	txhdr = (struct adm8211_tx_hdr *) skb_push(skb, sizeof(*txhdr));
 	memset(txhdr, 0, sizeof(*txhdr));
-	memcpy(txhdr->da, ieee80211_get_DA(&hdr), ETH_ALEN);
+	memcpy(txhdr->da, ieee80211_get_DA(hdr), ETH_ALEN);
 	txhdr->signal = plcp_signal;
 	txhdr->frame_body_size = cpu_to_le16(payload_len);
-	txhdr->frame_control = hdr.frame_control;
+	txhdr->frame_control = hdr->frame_control;
 
 	len = hdrlen + payload_len + FCS_LEN;
 	if (fc & IEEE80211_FCTL_PROTECTED)
@@ -1716,7 +1721,7 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
 
 	txhdr->retry_limit = control->retry_limit;
 
-	adm8211_tx_raw(dev, skb, plcp_signal, control, &hdr);
+	adm8211_tx_raw(dev, skb, plcp_signal, control, hdrlen);
 
 	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
index 926c66d..795d895 100644
--- a/drivers/net/wireless/adm8211.h
+++ b/drivers/net/wireless/adm8211.h
@@ -444,7 +444,7 @@ struct adm8211_tx_ring_info {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 	struct ieee80211_tx_control tx_control;
-	struct ieee80211_hdr hdr;
+	size_t hdrlen;
 };
 
 #define PLCP_SIGNAL_1M		0x0a
@@ -599,8 +599,8 @@ struct adm8211_priv {
 	dma_addr_t tx_ring_dma;
 	struct adm8211_rx_ring_info *rx_buffers;
 	struct adm8211_tx_ring_info *tx_buffers;
-	unsigned rx_ring_size, tx_ring_size;
-	unsigned cur_tx, dirty_tx, cur_rx;
+	unsigned int rx_ring_size, tx_ring_size;
+	unsigned int cur_tx, dirty_tx, cur_rx;
 
 	struct ieee80211_low_level_stats stats;
 	struct ieee80211_hw_mode modes[1];

-
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux