aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/libertas/assoc.c23
-rw-r--r--drivers/net/wireless/libertas/cmd.c71
-rw-r--r--drivers/net/wireless/libertas/cmd.h3
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c25
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h10
5 files changed, 75 insertions, 57 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 63bd692c7239..bd9cfe118c44 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -9,6 +9,7 @@
9#include "decl.h" 9#include "decl.h"
10#include "hostcmd.h" 10#include "hostcmd.h"
11#include "host.h" 11#include "host.h"
12#include "cmd.h"
12 13
13 14
14static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 15static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -165,11 +166,14 @@ done:
165static int update_channel(struct lbs_private *priv) 166static int update_channel(struct lbs_private *priv)
166{ 167{
167 int ret; 168 int ret;
169
168 /* the channel in f/w could be out of sync, get the current channel */ 170 /* the channel in f/w could be out of sync, get the current channel */
169 lbs_deb_enter(LBS_DEB_ASSOC); 171 lbs_deb_enter(LBS_DEB_ASSOC);
170 ret = lbs_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL, 172
171 CMD_OPT_802_11_RF_CHANNEL_GET, 173 ret = lbs_get_channel(priv);
172 CMD_OPTION_WAITFORRSP, 0, NULL); 174 if (ret > 0)
175 priv->curbssparams.channel = (u8) ret;
176
173 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 177 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
174 return ret; 178 return ret;
175} 179}
@@ -203,17 +207,16 @@ static int assoc_helper_channel(struct lbs_private *priv,
203 lbs_deb_assoc("ASSOC: channel: %d -> %d\n", 207 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
204 priv->curbssparams.channel, assoc_req->channel); 208 priv->curbssparams.channel, assoc_req->channel);
205 209
206 ret = lbs_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL, 210 ret = lbs_set_channel(priv, assoc_req->channel);
207 CMD_OPT_802_11_RF_CHANNEL_SET, 211 if (ret < 0)
208 CMD_OPTION_WAITFORRSP, 0, &assoc_req->channel);
209 if (ret < 0) {
210 lbs_deb_assoc("ASSOC: channel: error setting channel."); 212 lbs_deb_assoc("ASSOC: channel: error setting channel.");
211 }
212 213
214 /* FIXME: shouldn't need to grab the channel _again_ after setting
215 * it since the firmware is supposed to return the new channel, but
216 * whatever... */
213 ret = update_channel(priv); 217 ret = update_channel(priv);
214 if (ret < 0) { 218 if (ret < 0)
215 lbs_deb_assoc("ASSOC: channel: error getting channel."); 219 lbs_deb_assoc("ASSOC: channel: error getting channel.");
216 }
217 220
218 if (assoc_req->channel != priv->curbssparams.channel) { 221 if (assoc_req->channel != priv->curbssparams.channel) {
219 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d", 222 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index eff78792fc6f..32f9f880a15a 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -810,25 +810,65 @@ static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv,
810 return 0; 810 return 0;
811} 811}
812 812
813static int lbs_cmd_802_11_rf_channel(struct lbs_private *priv, 813/**
814 struct cmd_ds_command *cmd, 814 * @brief Get the radio channel
815 int option, void *pdata_buf) 815 *
816 * @param priv A pointer to struct lbs_private structure
817 *
818 * @return The channel on success, error on failure
819 */
820int lbs_get_channel(struct lbs_private *priv)
816{ 821{
817 struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel; 822 struct cmd_ds_802_11_rf_channel cmd;
823 int ret = 0;
818 824
819 lbs_deb_enter(LBS_DEB_CMD); 825 lbs_deb_enter(LBS_DEB_CMD);
820 cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
821 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
822 S_DS_GEN);
823 826
824 if (option == CMD_OPT_802_11_RF_CHANNEL_SET) { 827 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
825 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf)); 828 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
826 }
827 829
828 rfchan->action = cpu_to_le16(option); 830 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, cmd);
831 if (ret)
832 goto out;
829 833
830 lbs_deb_leave(LBS_DEB_CMD); 834 lbs_deb_cmd("current radio channel is %d\n", cmd.channel);
831 return 0; 835 ret = (int) cmd.channel;
836
837out:
838 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
839 return ret;
840}
841
842/**
843 * @brief Set the radio channel
844 *
845 * @param priv A pointer to struct lbs_private structure
846 * @param channel The desired channel, or 0 to clear a locked channel
847 *
848 * @return 0 on success, error on failure
849 */
850int lbs_set_channel(struct lbs_private *priv, u8 channel)
851{
852 struct cmd_ds_802_11_rf_channel cmd;
853 u8 old_channel = priv->curbssparams.channel;
854 int ret = 0;
855
856 lbs_deb_enter(LBS_DEB_CMD);
857
858 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
859 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
860 cmd.channel = cpu_to_le16(channel);
861
862 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, cmd);
863 if (ret)
864 goto out;
865
866 priv->curbssparams.channel = cmd.channel;
867 lbs_deb_cmd("channel switch from %d to %d\n", old_channel, cmd.channel);
868
869out:
870 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
871 return ret;
832} 872}
833 873
834static int lbs_cmd_802_11_rssi(struct lbs_private *priv, 874static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
@@ -1390,11 +1430,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1390 ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf); 1430 ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1391 break; 1431 break;
1392 1432
1393 case CMD_802_11_RF_CHANNEL:
1394 ret = lbs_cmd_802_11_rf_channel(priv, cmdptr,
1395 cmd_action, pdata_buf);
1396 break;
1397
1398 case CMD_802_11_RF_TX_POWER: 1433 case CMD_802_11_RF_TX_POWER:
1399 ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr, 1434 ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
1400 cmd_action, pdata_buf); 1435 cmd_action, pdata_buf);
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 4bd6f56281f6..5b02d73c8a0e 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -30,4 +30,7 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
30int lbs_get_data_rate(struct lbs_private *priv); 30int lbs_get_data_rate(struct lbs_private *priv);
31int lbs_set_data_rate(struct lbs_private *priv, u8 rate); 31int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
32 32
33int lbs_get_channel(struct lbs_private *priv);
34int lbs_set_channel(struct lbs_private *priv, u8 channel);
35
33#endif /* _LBS_CMD_H */ 36#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 797c943457eb..bf9941ecc239 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -325,28 +325,6 @@ static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
325 return 0; 325 return 0;
326} 326}
327 327
328static int lbs_ret_802_11_rf_channel(struct lbs_private *priv,
329 struct cmd_ds_command *resp)
330{
331 struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
332 u16 action = le16_to_cpu(rfchannel->action);
333 u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
334
335 lbs_deb_enter(LBS_DEB_CMD);
336
337 if (action == CMD_OPT_802_11_RF_CHANNEL_GET
338 && priv->curbssparams.channel != newchannel) {
339 lbs_deb_cmd("channel switch from %d to %d\n",
340 priv->curbssparams.channel, newchannel);
341
342 /* Update the channel again */
343 priv->curbssparams.channel = newchannel;
344 }
345
346 lbs_deb_enter(LBS_DEB_CMD);
347 return 0;
348}
349
350static int lbs_ret_802_11_rssi(struct lbs_private *priv, 328static int lbs_ret_802_11_rssi(struct lbs_private *priv,
351 struct cmd_ds_command *resp) 329 struct cmd_ds_command *resp)
352{ 330{
@@ -548,9 +526,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
548 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET): 526 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
549 ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp); 527 ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
550 break; 528 break;
551 case CMD_RET(CMD_802_11_RF_CHANNEL):
552 ret = lbs_ret_802_11_rf_channel(priv, resp);
553 break;
554 529
555 case CMD_RET(CMD_802_11_RSSI): 530 case CMD_RET(CMD_802_11_RSSI):
556 ret = lbs_ret_802_11_rssi(priv, resp); 531 ret = lbs_ret_802_11_rssi(priv, resp);
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index d51010c47b5b..7acb65116678 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -386,11 +386,13 @@ struct cmd_ds_802_11_inactivity_timeout {
386}; 386};
387 387
388struct cmd_ds_802_11_rf_channel { 388struct cmd_ds_802_11_rf_channel {
389 struct cmd_header hdr;
390
389 __le16 action; 391 __le16 action;
390 __le16 currentchannel; 392 __le16 channel;
391 __le16 rftype; 393 __le16 rftype; /* unused */
392 __le16 reserved; 394 __le16 reserved; /* unused */
393 u8 channellist[32]; 395 u8 channellist[32]; /* unused */
394}; 396};
395 397
396struct cmd_ds_802_11_rssi { 398struct cmd_ds_802_11_rssi {