aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-06-21 07:25:45 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-07-01 10:57:45 -0400
commita0f6b0a211fbdfbae603ffa434f0d9e691e55ab9 (patch)
tree61ecef92736d4a15dfe1a18c1fe5f7667761a0dc /drivers
parentc85eb6196958ae54eba3ff0660d2b5af3d58521a (diff)
iwlagn: add rx_free to transport layer
The transport layer ness to release all rx ressources. This function is an API for it. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c78
5 files changed, 62 insertions, 49 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3d971142786..a2c5c6b6cd3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -910,33 +910,6 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv)
910 iwlagn_rx_queue_restock(priv); 910 iwlagn_rx_queue_restock(priv);
911} 911}
912 912
913/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
914 * If an SKB has been detached, the POOL needs to have its SKB set to NULL
915 * This free routine walks the list of POOL entries and if SKB is set to
916 * non NULL it is unmapped and freed
917 */
918void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
919{
920 int i;
921 for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
922 if (rxq->pool[i].page != NULL) {
923 dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
924 PAGE_SIZE << priv->hw_params.rx_page_order,
925 DMA_FROM_DEVICE);
926 __iwl_free_pages(priv, rxq->pool[i].page);
927 rxq->pool[i].page = NULL;
928 }
929 }
930
931 dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE,
932 rxq->bd, rxq->bd_dma);
933 dma_free_coherent(priv->bus.dev,
934 sizeof(struct iwl_rb_status),
935 rxq->rb_stts, rxq->rb_stts_dma);
936 rxq->bd = NULL;
937 rxq->rb_stts = NULL;
938}
939
940int iwlagn_rxq_stop(struct iwl_priv *priv) 913int iwlagn_rxq_stop(struct iwl_priv *priv)
941{ 914{
942 915
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index b0657187158..f9127e7f36c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3718,8 +3718,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
3718 3718
3719 iwl_dealloc_ucode(priv); 3719 iwl_dealloc_ucode(priv);
3720 3720
3721 if (priv->rxq.bd) 3721 priv->trans.ops->rx_free(priv);
3722 iwlagn_rx_queue_free(priv, &priv->rxq);
3723 iwlagn_hw_txq_ctx_free(priv); 3722 iwlagn_hw_txq_ctx_free(priv);
3724 3723
3725 iwl_eeprom_free(priv); 3724 iwl_eeprom_free(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 7273297a6f4..877a6944dec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -193,7 +193,6 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv);
193void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); 193void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
194void iwlagn_rx_replenish(struct iwl_priv *priv); 194void iwlagn_rx_replenish(struct iwl_priv *priv);
195void iwlagn_rx_replenish_now(struct iwl_priv *priv); 195void iwlagn_rx_replenish_now(struct iwl_priv *priv);
196void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
197int iwlagn_rxq_stop(struct iwl_priv *priv); 196int iwlagn_rxq_stop(struct iwl_priv *priv);
198int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); 197int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
199void iwl_setup_rx_handlers(struct iwl_priv *priv); 198void iwl_setup_rx_handlers(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 7d3e55d0bc6..04b19a43139 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1233,9 +1233,11 @@ struct iwl_trans;
1233 * struct iwl_trans_ops - transport specific operations 1233 * struct iwl_trans_ops - transport specific operations
1234 1234
1235 * @rx_init: inits the rx memory, allocate it if needed 1235 * @rx_init: inits the rx memory, allocate it if needed
1236 *@rx_free: frees the rx memory
1236 */ 1237 */
1237struct iwl_trans_ops { 1238struct iwl_trans_ops {
1238 int (*rx_init)(struct iwl_priv *priv); 1239 int (*rx_init)(struct iwl_priv *priv);
1240 void (*rx_free)(struct iwl_priv *priv);
1239}; 1241};
1240 1242
1241struct iwl_trans { 1243struct iwl_trans {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index ccf73ff6395..1f5834b8a63 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -60,7 +60,7 @@
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 * 61 *
62 *****************************************************************************/ 62 *****************************************************************************/
63 #include "iwl-dev.h" 63#include "iwl-dev.h"
64#include "iwl-trans.h" 64#include "iwl-trans.h"
65 65
66static int iwl_trans_rx_alloc(struct iwl_priv *priv) 66static int iwl_trans_rx_alloc(struct iwl_priv *priv)
@@ -78,12 +78,11 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv)
78 return -EINVAL; 78 return -EINVAL;
79 79
80 /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ 80 /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
81 /*Every descriptor is an __le32, hence its */ 81 rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
82 rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, 82 &rxq->bd_dma, GFP_KERNEL);
83 GFP_KERNEL);
84 if (!rxq->bd) 83 if (!rxq->bd)
85 goto err_bd; 84 goto err_bd;
86 memset(rxq->bd, 0, 4 * RX_QUEUE_SIZE); 85 memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
87 86
88 /*Allocate the driver's pointer to receive buffer status */ 87 /*Allocate the driver's pointer to receive buffer status */
89 rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), 88 rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
@@ -95,28 +94,18 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv)
95 return 0; 94 return 0;
96 95
97err_rb_stts: 96err_rb_stts:
98 dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); 97 dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
98 rxq->bd, rxq->bd_dma);
99 memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); 99 memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
100 rxq->bd = NULL; 100 rxq->bd = NULL;
101err_bd: 101err_bd:
102 return -ENOMEM; 102 return -ENOMEM;
103} 103}
104 104
105static int iwl_trans_rx_init(struct iwl_priv *priv) 105static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv)
106{ 106{
107 struct iwl_rx_queue *rxq = &priv->rxq; 107 struct iwl_rx_queue *rxq = &priv->rxq;
108 int i, err; 108 int i;
109 unsigned long flags;
110
111 if (!rxq->bd) {
112 err = iwl_trans_rx_alloc(priv);
113 if (err)
114 return err;
115 }
116
117 spin_lock_irqsave(&rxq->lock, flags);
118 INIT_LIST_HEAD(&rxq->rx_free);
119 INIT_LIST_HEAD(&rxq->rx_used);
120 109
121 /* Fill the rx_used queue with _all_ of the Rx buffers */ 110 /* Fill the rx_used queue with _all_ of the Rx buffers */
122 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { 111 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
@@ -131,6 +120,25 @@ static int iwl_trans_rx_init(struct iwl_priv *priv)
131 } 120 }
132 list_add_tail(&rxq->pool[i].list, &rxq->rx_used); 121 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
133 } 122 }
123}
124
125static int iwl_trans_rx_init(struct iwl_priv *priv)
126{
127 struct iwl_rx_queue *rxq = &priv->rxq;
128 int i, err;
129 unsigned long flags;
130
131 if (!rxq->bd) {
132 err = iwl_trans_rx_alloc(priv);
133 if (err)
134 return err;
135 }
136
137 spin_lock_irqsave(&rxq->lock, flags);
138 INIT_LIST_HEAD(&rxq->rx_free);
139 INIT_LIST_HEAD(&rxq->rx_used);
140
141 iwl_trans_rxq_free_rx_bufs(priv);
134 142
135 for (i = 0; i < RX_QUEUE_SIZE; i++) 143 for (i = 0; i < RX_QUEUE_SIZE; i++)
136 rxq->queue[i] = NULL; 144 rxq->queue[i] = NULL;
@@ -145,8 +153,40 @@ static int iwl_trans_rx_init(struct iwl_priv *priv)
145 return 0; 153 return 0;
146} 154}
147 155
156static void iwl_trans_rx_free(struct iwl_priv *priv)
157{
158 struct iwl_rx_queue *rxq = &priv->rxq;
159 unsigned long flags;
160
161 /*if rxq->bd is NULL, it means that nothing has been allocated,
162 * exit now */
163 if (!rxq->bd) {
164 IWL_DEBUG_INFO(priv, "Free NULL rx context\n");
165 return;
166 }
167
168 spin_lock_irqsave(&rxq->lock, flags);
169 iwl_trans_rxq_free_rx_bufs(priv);
170 spin_unlock_irqrestore(&rxq->lock, flags);
171
172 dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE,
173 rxq->bd, rxq->bd_dma);
174 memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
175 rxq->bd = NULL;
176
177 if (rxq->rb_stts)
178 dma_free_coherent(priv->bus.dev,
179 sizeof(struct iwl_rb_status),
180 rxq->rb_stts, rxq->rb_stts_dma);
181 else
182 IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n");
183 memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
184 rxq->rb_stts = NULL;
185}
186
148static const struct iwl_trans_ops trans_ops = { 187static const struct iwl_trans_ops trans_ops = {
149 .rx_init = iwl_trans_rx_init, 188 .rx_init = iwl_trans_rx_init,
189 .rx_free = iwl_trans_rx_free,
150}; 190};
151 191
152void iwl_trans_register(struct iwl_trans *trans) 192void iwl_trans_register(struct iwl_trans *trans)