diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2011-06-21 07:25:45 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-07-01 10:57:45 -0400 |
commit | a0f6b0a211fbdfbae603ffa434f0d9e691e55ab9 (patch) | |
tree | 61ecef92736d4a15dfe1a18c1fe5f7667761a0dc /drivers | |
parent | c85eb6196958ae54eba3ff0660d2b5af3d58521a (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.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 78 |
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 3d971142786e..a2c5c6b6cd3a 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 | */ | ||
918 | void 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 | |||
940 | int iwlagn_rxq_stop(struct iwl_priv *priv) | 913 | int 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 b06571871580..f9127e7f36c7 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 7273297a6f40..877a6944dec3 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); | |||
193 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); | 193 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); |
194 | void iwlagn_rx_replenish(struct iwl_priv *priv); | 194 | void iwlagn_rx_replenish(struct iwl_priv *priv); |
195 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); | 195 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); |
196 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
197 | int iwlagn_rxq_stop(struct iwl_priv *priv); | 196 | int iwlagn_rxq_stop(struct iwl_priv *priv); |
198 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | 197 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); |
199 | void iwl_setup_rx_handlers(struct iwl_priv *priv); | 198 | void 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 7d3e55d0bc62..04b19a431397 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 | */ |
1237 | struct iwl_trans_ops { | 1238 | struct 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 | ||
1241 | struct iwl_trans { | 1243 | struct iwl_trans { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ccf73ff63956..1f5834b8a639 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 | ||
66 | static int iwl_trans_rx_alloc(struct iwl_priv *priv) | 66 | static 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 | ||
97 | err_rb_stts: | 96 | err_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; |
101 | err_bd: | 101 | err_bd: |
102 | return -ENOMEM; | 102 | return -ENOMEM; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int iwl_trans_rx_init(struct iwl_priv *priv) | 105 | static 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 | |||
125 | static 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 | ||
156 | static 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 | |||
148 | static const struct iwl_trans_ops trans_ops = { | 187 | static 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 | ||
152 | void iwl_trans_register(struct iwl_trans *trans) | 192 | void iwl_trans_register(struct iwl_trans *trans) |