diff options
author | Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 2013-07-11 11:03:40 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-07-22 16:54:38 -0400 |
commit | f88f113a54f02df62608ec263e8a3ff7e81cfce2 (patch) | |
tree | 49c12349e02fba2c095ba98e3fdc6f8ce13ddb2b /drivers/net/wireless/ath/wil6210 | |
parent | 03269c658b7a2f6ccfa44d7270da8446881f9552 (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.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 58 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 10 |
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 = ⅆ | 115 | struct vring_tx_desc dd, *d = ⅆ |
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 = ⅆ | 134 | struct vring_rx_desc dd, *d = ⅆ |
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 = ⅆ | 828 | struct vring_tx_desc dd, *d = ⅆ |
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 | */ | ||
189 | struct wil_ctx { | ||
190 | struct sk_buff *skb; | ||
191 | u8 mapped_as_page:1; | ||
192 | }; | ||
193 | |||
186 | union vring_desc; | 194 | union vring_desc; |
187 | 195 | ||
188 | struct vring { | 196 | struct 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 | ||
198 | enum { /* for wil6210_priv.status */ | 206 | enum { /* for wil6210_priv.status */ |