aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2013-07-11 11:03:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-07-22 16:54:38 -0400
commitf88f113a54f02df62608ec263e8a3ff7e81cfce2 (patch)
tree49c12349e02fba2c095ba98e3fdc6f8ce13ddb2b /drivers/net/wireless/ath/wil6210
parent03269c658b7a2f6ccfa44d7270da8446881f9552 (diff)
wil6210: Introduce struct for sw context
Enable adding more data to the SW context. For now, add flag "mapped_as_page", to separate decisions on free-ing skb and type of DMA mapping. This allows linking skb itself to any descriptor of fragmented skb. Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/wil6210')
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c58
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h10
3 files changed, 44 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index e8308ec30970..971ce46a6b5f 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -51,7 +51,7 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
51 if ((i % 64) == 0 && (i != 0)) 51 if ((i % 64) == 0 && (i != 0))
52 seq_printf(s, "\n"); 52 seq_printf(s, "\n");
53 seq_printf(s, "%s", (d->dma.status & BIT(0)) ? 53 seq_printf(s, "%s", (d->dma.status & BIT(0)) ?
54 "S" : (vring->ctx[i] ? "H" : "h")); 54 "S" : (vring->ctx[i].skb ? "H" : "h"));
55 } 55 }
56 seq_printf(s, "\n"); 56 seq_printf(s, "\n");
57 } 57 }
@@ -406,7 +406,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
406 volatile struct vring_tx_desc *d = 406 volatile struct vring_tx_desc *d =
407 &(vring->va[dbg_txdesc_index].tx); 407 &(vring->va[dbg_txdesc_index].tx);
408 volatile u32 *u = (volatile u32 *)d; 408 volatile u32 *u = (volatile u32 *)d;
409 struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; 409 struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb;
410 410
411 seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); 411 seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index);
412 seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", 412 seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index dd5f35eb64b4..44cdd2a3dff3 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -70,7 +70,7 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
70 70
71 vring->swhead = 0; 71 vring->swhead = 0;
72 vring->swtail = 0; 72 vring->swtail = 0;
73 vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); 73 vring->ctx = kcalloc(vring->size, sizeof(vring->ctx[0]), GFP_KERNEL);
74 if (!vring->ctx) { 74 if (!vring->ctx) {
75 vring->va = NULL; 75 vring->va = NULL;
76 return -ENOMEM; 76 return -ENOMEM;
@@ -108,39 +108,39 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
108 108
109 while (!wil_vring_is_empty(vring)) { 109 while (!wil_vring_is_empty(vring)) {
110 dma_addr_t pa; 110 dma_addr_t pa;
111 struct sk_buff *skb;
112 u16 dmalen; 111 u16 dmalen;
112 struct wil_ctx *ctx;
113 113
114 if (tx) { 114 if (tx) {
115 struct vring_tx_desc dd, *d = &dd; 115 struct vring_tx_desc dd, *d = &dd;
116 volatile struct vring_tx_desc *_d = 116 volatile struct vring_tx_desc *_d =
117 &vring->va[vring->swtail].tx; 117 &vring->va[vring->swtail].tx;
118 118
119 ctx = &vring->ctx[vring->swtail];
119 *d = *_d; 120 *d = *_d;
120 pa = wil_desc_addr(&d->dma.addr); 121 pa = wil_desc_addr(&d->dma.addr);
121 dmalen = le16_to_cpu(d->dma.length); 122 dmalen = le16_to_cpu(d->dma.length);
122 skb = vring->ctx[vring->swtail]; 123 if (vring->ctx[vring->swtail].mapped_as_page) {
123 if (skb) {
124 dma_unmap_single(dev, pa, dmalen,
125 DMA_TO_DEVICE);
126 dev_kfree_skb_any(skb);
127 vring->ctx[vring->swtail] = NULL;
128 } else {
129 dma_unmap_page(dev, pa, dmalen, 124 dma_unmap_page(dev, pa, dmalen,
130 DMA_TO_DEVICE); 125 DMA_TO_DEVICE);
126 } else {
127 dma_unmap_single(dev, pa, dmalen,
128 DMA_TO_DEVICE);
131 } 129 }
130 if (ctx->skb)
131 dev_kfree_skb_any(ctx->skb);
132 vring->swtail = wil_vring_next_tail(vring); 132 vring->swtail = wil_vring_next_tail(vring);
133 } else { /* rx */ 133 } else { /* rx */
134 struct vring_rx_desc dd, *d = &dd; 134 struct vring_rx_desc dd, *d = &dd;
135 volatile struct vring_rx_desc *_d = 135 volatile struct vring_rx_desc *_d =
136 &vring->va[vring->swhead].rx; 136 &vring->va[vring->swhead].rx;
137 137
138 ctx = &vring->ctx[vring->swhead];
138 *d = *_d; 139 *d = *_d;
139 pa = wil_desc_addr(&d->dma.addr); 140 pa = wil_desc_addr(&d->dma.addr);
140 dmalen = le16_to_cpu(d->dma.length); 141 dmalen = le16_to_cpu(d->dma.length);
141 skb = vring->ctx[vring->swhead];
142 dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); 142 dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);
143 kfree_skb(skb); 143 kfree_skb(ctx->skb);
144 wil_vring_advance_head(vring, 1); 144 wil_vring_advance_head(vring, 1);
145 } 145 }
146 } 146 }
@@ -187,7 +187,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
187 d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ 187 d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
188 d->dma.length = cpu_to_le16(sz); 188 d->dma.length = cpu_to_le16(sz);
189 *_d = *d; 189 *_d = *d;
190 vring->ctx[i] = skb; 190 vring->ctx[i].skb = skb;
191 191
192 return 0; 192 return 0;
193} 193}
@@ -352,11 +352,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
352 return NULL; 352 return NULL;
353 } 353 }
354 354
355 skb = vring->ctx[vring->swhead]; 355 skb = vring->ctx[vring->swhead].skb;
356 d = wil_skb_rxdesc(skb); 356 d = wil_skb_rxdesc(skb);
357 *d = *_d; 357 *d = *_d;
358 pa = wil_desc_addr(&d->dma.addr); 358 pa = wil_desc_addr(&d->dma.addr);
359 vring->ctx[vring->swhead] = NULL; 359 vring->ctx[vring->swhead].skb = NULL;
360 wil_vring_advance_head(vring, 1); 360 wil_vring_advance_head(vring, 1);
361 361
362 dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); 362 dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
@@ -703,7 +703,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
703 if (unlikely(dma_mapping_error(dev, pa))) 703 if (unlikely(dma_mapping_error(dev, pa)))
704 goto dma_error; 704 goto dma_error;
705 wil_tx_desc_map(d, pa, len, vring_index); 705 wil_tx_desc_map(d, pa, len, vring_index);
706 vring->ctx[i] = NULL; 706 vring->ctx[i].mapped_as_page = 1;
707 *_d = *d; 707 *_d = *d;
708 } 708 }
709 /* for the last seg only */ 709 /* for the last seg only */
@@ -724,7 +724,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
724 * to prevent skb release before accounting 724 * to prevent skb release before accounting
725 * in case of immediate "tx done" 725 * in case of immediate "tx done"
726 */ 726 */
727 vring->ctx[i] = skb_get(skb); 727 vring->ctx[i].skb = skb_get(skb);
728 728
729 return 0; 729 return 0;
730 dma_error: 730 dma_error:
@@ -732,6 +732,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
732 /* Note: increment @f to operate with positive index */ 732 /* Note: increment @f to operate with positive index */
733 for (f++; f > 0; f--) { 733 for (f++; f > 0; f--) {
734 u16 dmalen; 734 u16 dmalen;
735 struct wil_ctx *ctx = &vring->ctx[i];
735 736
736 i = (swhead + f) % vring->size; 737 i = (swhead + f) % vring->size;
737 _d = &(vring->va[i].tx); 738 _d = &(vring->va[i].tx);
@@ -739,10 +740,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
739 _d->dma.status = TX_DMA_STATUS_DU; 740 _d->dma.status = TX_DMA_STATUS_DU;
740 pa = wil_desc_addr(&d->dma.addr); 741 pa = wil_desc_addr(&d->dma.addr);
741 dmalen = le16_to_cpu(d->dma.length); 742 dmalen = le16_to_cpu(d->dma.length);
742 if (vring->ctx[i]) 743 if (ctx->mapped_as_page)
743 dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
744 else
745 dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); 744 dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
745 else
746 dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
747
748 if (ctx->skb)
749 dev_kfree_skb_any(ctx->skb);
750
751 memset(ctx, 0, sizeof(*ctx));
746 } 752 }
747 753
748 return -EINVAL; 754 return -EINVAL;
@@ -821,8 +827,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
821 &vring->va[vring->swtail].tx; 827 &vring->va[vring->swtail].tx;
822 struct vring_tx_desc dd, *d = &dd; 828 struct vring_tx_desc dd, *d = &dd;
823 dma_addr_t pa; 829 dma_addr_t pa;
824 struct sk_buff *skb;
825 u16 dmalen; 830 u16 dmalen;
831 struct wil_ctx *ctx = &vring->ctx[vring->swtail];
832 struct sk_buff *skb = ctx->skb;
826 833
827 *d = *_d; 834 *d = *_d;
828 835
@@ -840,7 +847,11 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
840 (const void *)d, sizeof(*d), false); 847 (const void *)d, sizeof(*d), false);
841 848
842 pa = wil_desc_addr(&d->dma.addr); 849 pa = wil_desc_addr(&d->dma.addr);
843 skb = vring->ctx[vring->swtail]; 850 if (ctx->mapped_as_page)
851 dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
852 else
853 dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
854
844 if (skb) { 855 if (skb) {
845 if (d->dma.error == 0) { 856 if (d->dma.error == 0) {
846 ndev->stats.tx_packets++; 857 ndev->stats.tx_packets++;
@@ -849,12 +860,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
849 ndev->stats.tx_errors++; 860 ndev->stats.tx_errors++;
850 } 861 }
851 862
852 dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
853 dev_kfree_skb_any(skb); 863 dev_kfree_skb_any(skb);
854 vring->ctx[vring->swtail] = NULL;
855 } else {
856 dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
857 } 864 }
865 memset(ctx, 0, sizeof(*ctx));
858 /* 866 /*
859 * There is no need to touch HW descriptor: 867 * There is no need to touch HW descriptor:
860 * - ststus bit TX_DMA_STATUS_DU is set by design, 868 * - ststus bit TX_DMA_STATUS_DU is set by design,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 129c480c8a20..c4a51638736a 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -183,6 +183,14 @@ struct pending_wmi_event {
183 } __packed event; 183 } __packed event;
184}; 184};
185 185
186/**
187 * struct wil_ctx - software context for Vring descriptor
188 */
189struct wil_ctx {
190 struct sk_buff *skb;
191 u8 mapped_as_page:1;
192};
193
186union vring_desc; 194union vring_desc;
187 195
188struct vring { 196struct vring {
@@ -192,7 +200,7 @@ struct vring {
192 u32 swtail; 200 u32 swtail;
193 u32 swhead; 201 u32 swhead;
194 u32 hwtail; /* write here to inform hw */ 202 u32 hwtail; /* write here to inform hw */
195 void **ctx; /* void *ctx[size] - software context */ 203 struct wil_ctx *ctx; /* ctx[size] - software context */
196}; 204};
197 205
198enum { /* for wil6210_priv.status */ 206enum { /* for wil6210_priv.status */