diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-05-13 14:57:40 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-05-13 15:00:41 -0400 |
commit | 4ce7cc2b09553a91d4aea014c39674685715173a (patch) | |
tree | 0a2e4b8ae8852a6404c479a7b605ae4b0af6b72d /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | 4c42db0f04e55d48f0ea9f424144a5211b7a155c (diff) |
iwlagn: support multiple TBs per command
The current "huge" command handling is a bit
confusing, and very limited since only one
command may be huge at a time. Additionally,
we often copy data around quite pointlessly
since we could instead map the existing scan
buffer for example and use it directly.
This patch makes that possible. The first
change is that multiple buffers may be given
to each command (this change was prepared
earlier so callsites don't need to change).
Each of those can be mapped attached to a TB
in the TFD, and the command header can use a
TB (the first one) in the TFD as well.
Doing this allows getting rid of huge commands
in favour of mapping existing buffers. The
beacon transmission is also optimised to not
copy the SKB at all but use multiple TBs.
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/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 28 |
1 files changed, 12 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2bb08d7e0674..675b9a644a0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
134 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 134 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
135 | struct iwl_host_cmd cmd = { | 135 | struct iwl_host_cmd cmd = { |
136 | .id = REPLY_TX_BEACON, | 136 | .id = REPLY_TX_BEACON, |
137 | .flags = CMD_SIZE_HUGE, | ||
138 | }; | 137 | }; |
139 | u32 frame_size; | 138 | u32 frame_size; |
140 | u32 rate_flags; | 139 | u32 rate_flags; |
141 | u32 rate; | 140 | u32 rate; |
142 | int err; | ||
143 | 141 | ||
144 | /* | 142 | /* |
145 | * We have to set up the TX command, the TX Beacon command, and the | 143 | * We have to set up the TX command, the TX Beacon command, and the |
@@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
156 | if (WARN_ON(!priv->beacon_skb)) | 154 | if (WARN_ON(!priv->beacon_skb)) |
157 | return -EINVAL; | 155 | return -EINVAL; |
158 | 156 | ||
159 | /* Allocate beacon memory */ | 157 | /* Allocate beacon command */ |
160 | tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, | 158 | if (!priv->beacon_cmd) |
161 | GFP_KERNEL); | 159 | priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL); |
160 | tx_beacon_cmd = priv->beacon_cmd; | ||
162 | if (!tx_beacon_cmd) | 161 | if (!tx_beacon_cmd) |
163 | return -ENOMEM; | 162 | return -ENOMEM; |
164 | 163 | ||
165 | frame_size = priv->beacon_skb->len; | 164 | frame_size = priv->beacon_skb->len; |
166 | 165 | ||
167 | /* Set up TX beacon contents */ | ||
168 | memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); | ||
169 | |||
170 | /* Set up TX command fields */ | 166 | /* Set up TX command fields */ |
171 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 167 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
172 | tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; | 168 | tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; |
@@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
175 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | 171 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; |
176 | 172 | ||
177 | /* Set up TX beacon command fields */ | 173 | /* Set up TX beacon command fields */ |
178 | iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, | 174 | iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data, |
179 | frame_size); | 175 | frame_size); |
180 | 176 | ||
181 | /* Set up packet rate and flags */ | 177 | /* Set up packet rate and flags */ |
@@ -189,15 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
189 | rate_flags); | 185 | rate_flags); |
190 | 186 | ||
191 | /* Submit command */ | 187 | /* Submit command */ |
192 | cmd.len[0] = sizeof(*tx_beacon_cmd) + frame_size; | 188 | cmd.len[0] = sizeof(*tx_beacon_cmd); |
193 | cmd.data[0] = tx_beacon_cmd; | 189 | cmd.data[0] = tx_beacon_cmd; |
190 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
191 | cmd.len[1] = frame_size; | ||
192 | cmd.data[1] = priv->beacon_skb->data; | ||
193 | cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; | ||
194 | 194 | ||
195 | err = iwl_send_cmd_sync(priv, &cmd); | 195 | return iwl_send_cmd_sync(priv, &cmd); |
196 | |||
197 | /* Free temporary storage */ | ||
198 | kfree(tx_beacon_cmd); | ||
199 | |||
200 | return err; | ||
201 | } | 196 | } |
202 | 197 | ||
203 | static void iwl_bg_beacon_update(struct work_struct *work) | 198 | static void iwl_bg_beacon_update(struct work_struct *work) |
@@ -3246,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3246 | iwlcore_free_geos(priv); | 3241 | iwlcore_free_geos(priv); |
3247 | iwl_free_channel_map(priv); | 3242 | iwl_free_channel_map(priv); |
3248 | kfree(priv->scan_cmd); | 3243 | kfree(priv->scan_cmd); |
3244 | kfree(priv->beacon_cmd); | ||
3249 | } | 3245 | } |
3250 | 3246 | ||
3251 | struct ieee80211_ops iwlagn_hw_ops = { | 3247 | struct ieee80211_ops iwlagn_hw_ops = { |