aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-04-29 12:48:14 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-05-06 13:45:53 -0400
commit8a98d49ec1f38d9f3eef7e34f148c3f1f5590fdf (patch)
tree5c4b2efe6a175f48f0bd1236a0f433616c57e8bc /drivers/net/wireless
parent46975f78fe1f480682e51c9acb03a5089b784cb6 (diff)
iwlagn: remove frame pre-allocation
The frame pre-allocation is quite a bit of complex code, all to avoid a single allocation. Remove it and consolidate the beacon sending code. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c137
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h13
2 files changed, 25 insertions, 125 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 09fe841f0281..3ecc3198d9bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -102,70 +102,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
102 } 102 }
103} 103}
104 104
105static void iwl_clear_free_frames(struct iwl_priv *priv)
106{
107 struct list_head *element;
108
109 IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
110 priv->frames_count);
111
112 while (!list_empty(&priv->free_frames)) {
113 element = priv->free_frames.next;
114 list_del(element);
115 kfree(list_entry(element, struct iwl_frame, list));
116 priv->frames_count--;
117 }
118
119 if (priv->frames_count) {
120 IWL_WARN(priv, "%d frames still in use. Did we lose one?\n",
121 priv->frames_count);
122 priv->frames_count = 0;
123 }
124}
125
126static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
127{
128 struct iwl_frame *frame;
129 struct list_head *element;
130 if (list_empty(&priv->free_frames)) {
131 frame = kzalloc(sizeof(*frame), GFP_KERNEL);
132 if (!frame) {
133 IWL_ERR(priv, "Could not allocate frame!\n");
134 return NULL;
135 }
136
137 priv->frames_count++;
138 return frame;
139 }
140
141 element = priv->free_frames.next;
142 list_del(element);
143 return list_entry(element, struct iwl_frame, list);
144}
145
146static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
147{
148 memset(frame, 0, sizeof(*frame));
149 list_add(&frame->list, &priv->free_frames);
150}
151
152static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
153 struct ieee80211_hdr *hdr,
154 int left)
155{
156 lockdep_assert_held(&priv->mutex);
157
158 if (!priv->beacon_skb)
159 return 0;
160
161 if (priv->beacon_skb->len > left)
162 return 0;
163
164 memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
165
166 return priv->beacon_skb->len;
167}
168
169/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ 105/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
170static void iwl_set_beacon_tim(struct iwl_priv *priv, 106static void iwl_set_beacon_tim(struct iwl_priv *priv,
171 struct iwl_tx_beacon_cmd *tx_beacon_cmd, 107 struct iwl_tx_beacon_cmd *tx_beacon_cmd,
@@ -193,13 +129,18 @@ static void iwl_set_beacon_tim(struct iwl_priv *priv,
193 IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); 129 IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
194} 130}
195 131
196static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, 132int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
197 struct iwl_frame *frame)
198{ 133{
199 struct iwl_tx_beacon_cmd *tx_beacon_cmd; 134 struct iwl_tx_beacon_cmd *tx_beacon_cmd;
135 struct iwl_host_cmd cmd = {
136 .id = REPLY_TX_BEACON,
137 .flags = CMD_SIZE_HUGE,
138 };
200 u32 frame_size; 139 u32 frame_size;
201 u32 rate_flags; 140 u32 rate_flags;
202 u32 rate; 141 u32 rate;
142 int err;
143
203 /* 144 /*
204 * We have to set up the TX command, the TX Beacon command, and the 145 * We have to set up the TX command, the TX Beacon command, and the
205 * beacon contents. 146 * beacon contents.
@@ -212,17 +153,19 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
212 return 0; 153 return 0;
213 } 154 }
214 155
215 /* Initialize memory */ 156 if (WARN_ON(!priv->beacon_skb))
216 tx_beacon_cmd = &frame->u.beacon; 157 return -EINVAL;
217 memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); 158
159 /* Allocate beacon memory */
160 tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len,
161 GFP_KERNEL);
162 if (!tx_beacon_cmd)
163 return -ENOMEM;
164
165 frame_size = priv->beacon_skb->len;
218 166
219 /* Set up TX beacon contents */ 167 /* Set up TX beacon contents */
220 frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, 168 memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size);
221 sizeof(frame->u) - sizeof(*tx_beacon_cmd));
222 if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
223 return 0;
224 if (!frame_size)
225 return 0;
226 169
227 /* Set up TX command fields */ 170 /* Set up TX command fields */
228 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); 171 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
@@ -245,41 +188,16 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
245 tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, 188 tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
246 rate_flags); 189 rate_flags);
247 190
248 return sizeof(*tx_beacon_cmd) + frame_size; 191 /* Submit command */
249} 192 cmd.len = sizeof(*tx_beacon_cmd) + frame_size;
193 cmd.data = tx_beacon_cmd;
250 194
251int iwlagn_send_beacon_cmd(struct iwl_priv *priv) 195 err = iwl_send_cmd_sync(priv, &cmd);
252{
253 struct iwl_frame *frame;
254 unsigned int frame_size;
255 int rc;
256 struct iwl_host_cmd cmd = {
257 .id = REPLY_TX_BEACON,
258 .flags = CMD_SIZE_HUGE,
259 };
260
261 frame = iwl_get_free_frame(priv);
262 if (!frame) {
263 IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
264 "command.\n");
265 return -ENOMEM;
266 }
267
268 frame_size = iwl_hw_get_beacon_cmd(priv, frame);
269 if (!frame_size) {
270 IWL_ERR(priv, "Error configuring the beacon command\n");
271 iwl_free_frame(priv, frame);
272 return -EINVAL;
273 }
274
275 cmd.len = frame_size;
276 cmd.data = &frame->u.cmd[0];
277
278 rc = iwl_send_cmd_sync(priv, &cmd);
279 196
280 iwl_free_frame(priv, frame); 197 /* Free temporary storage */
198 kfree(tx_beacon_cmd);
281 199
282 return rc; 200 return err;
283} 201}
284 202
285static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) 203static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
@@ -2356,9 +2274,6 @@ static void __iwl_down(struct iwl_priv *priv)
2356 2274
2357 dev_kfree_skb(priv->beacon_skb); 2275 dev_kfree_skb(priv->beacon_skb);
2358 priv->beacon_skb = NULL; 2276 priv->beacon_skb = NULL;
2359
2360 /* clear out any free frames */
2361 iwl_clear_free_frames(priv);
2362} 2277}
2363 2278
2364static void iwl_down(struct iwl_priv *priv) 2279static void iwl_down(struct iwl_priv *priv)
@@ -3416,8 +3331,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
3416 spin_lock_init(&priv->sta_lock); 3331 spin_lock_init(&priv->sta_lock);
3417 spin_lock_init(&priv->hcmd_lock); 3332 spin_lock_init(&priv->hcmd_lock);
3418 3333
3419 INIT_LIST_HEAD(&priv->free_frames);
3420
3421 mutex_init(&priv->mutex); 3334 mutex_init(&priv->mutex);
3422 3335
3423 priv->ieee_channels = NULL; 3336 priv->ieee_channels = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 3d28ad258077..2fd752a9aac8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -238,15 +238,6 @@ struct iwl_channel_info {
238#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) 238#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
239#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) 239#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
240 240
241struct iwl_frame {
242 union {
243 struct ieee80211_hdr frame;
244 struct iwl_tx_beacon_cmd beacon;
245 u8 raw[IEEE80211_FRAME_LEN];
246 u8 cmd[360];
247 } u;
248 struct list_head list;
249};
250 241
251#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) 242#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
252#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) 243#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
@@ -1188,10 +1179,6 @@ struct iwl_priv {
1188 struct ieee80211_rate *ieee_rates; 1179 struct ieee80211_rate *ieee_rates;
1189 struct iwl_cfg *cfg; 1180 struct iwl_cfg *cfg;
1190 1181
1191 /* temporary frame storage list */
1192 struct list_head free_frames;
1193 int frames_count;
1194
1195 enum ieee80211_band band; 1182 enum ieee80211_band band;
1196 1183
1197 void (*pre_rx_handler)(struct iwl_priv *priv, 1184 void (*pre_rx_handler)(struct iwl_priv *priv,