aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-trans.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c78
1 files changed, 59 insertions, 19 deletions
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
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)