diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-04-29 12:48:14 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-05-06 13:45:53 -0400 |
commit | 8a98d49ec1f38d9f3eef7e34f148c3f1f5590fdf (patch) | |
tree | 5c4b2efe6a175f48f0bd1236a0f433616c57e8bc /drivers/net/wireless | |
parent | 46975f78fe1f480682e51c9acb03a5089b784cb6 (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.c | 137 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 13 |
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 | ||
105 | static 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 | |||
126 | static 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 | |||
146 | static 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 | |||
152 | static 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 */ |
170 | static void iwl_set_beacon_tim(struct iwl_priv *priv, | 106 | static 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 | ||
196 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | 132 | int 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 | ||
251 | int 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 | ||
285 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 203 | static 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 | ||
2364 | static void iwl_down(struct iwl_priv *priv) | 2279 | static 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 | ||
241 | struct 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, |