aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2008-08-19 15:15:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-29 16:24:06 -0400
commit87c8c72d532f96257162f978d5945dcf7f0df19e (patch)
tree71f270c1844e74ba41a6fe347e53f035db923e7d
parent095f695cbb07281682462da0618fffabb499d0be (diff)
libertas: convert CMD_802_11_RF_TX_POWER to a direct command
And while we're at it, grab min/max TX power from the firmware and use that to validate incoming TX power requests from WEXT. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/libertas/cmd.c85
-rw-r--r--drivers/net/wireless/libertas/cmd.h4
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c19
-rw-r--r--drivers/net/wireless/libertas/dev.h4
-rw-r--r--drivers/net/wireless/libertas/host.h10
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h7
-rw-r--r--drivers/net/wireless/libertas/main.c13
-rw-r--r--drivers/net/wireless/libertas/wext.c83
8 files changed, 111 insertions, 114 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index af5fd709887f..c0db988926bf 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -614,47 +614,67 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
614 return 0; 614 return 0;
615} 615}
616 616
617static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd, 617/**
618 u16 cmd_action, void *pdata_buf) 618 * @brief Get the min, max, and current TX power
619 *
620 * @param priv A pointer to struct lbs_private structure
621 * @param curlevel Current power level in dBm
622 * @param minlevel Minimum supported power level in dBm (optional)
623 * @param maxlevel Maximum supported power level in dBm (optional)
624 *
625 * @return 0 on success, error on failure
626 */
627int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
628 s16 *maxlevel)
619{ 629{
620 630 struct cmd_ds_802_11_rf_tx_power cmd;
621 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp; 631 int ret;
622 632
623 lbs_deb_enter(LBS_DEB_CMD); 633 lbs_deb_enter(LBS_DEB_CMD);
624 634
625 cmd->size = 635 memset(&cmd, 0, sizeof(cmd));
626 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN); 636 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
627 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER); 637 cmd.action = cpu_to_le16(CMD_ACT_GET);
628 prtp->action = cpu_to_le16(cmd_action); 638
639 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
640 if (ret == 0) {
641 *curlevel = le16_to_cpu(cmd.curlevel);
642 if (minlevel)
643 *minlevel = le16_to_cpu(cmd.minlevel);
644 if (maxlevel)
645 *maxlevel = le16_to_cpu(cmd.maxlevel);
646 }
629 647
630 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", 648 lbs_deb_leave(LBS_DEB_CMD);
631 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command), 649 return ret;
632 le16_to_cpu(prtp->action)); 650}
633 651
634 switch (cmd_action) { 652/**
635 case CMD_ACT_TX_POWER_OPT_GET: 653 * @brief Set the TX power
636 prtp->action = cpu_to_le16(CMD_ACT_GET); 654 *
637 prtp->currentlevel = 0; 655 * @param priv A pointer to struct lbs_private structure
638 break; 656 * @param dbm The desired power level in dBm
657 *
658 * @return 0 on success, error on failure
659 */
660int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
661{
662 struct cmd_ds_802_11_rf_tx_power cmd;
663 int ret;
639 664
640 case CMD_ACT_TX_POWER_OPT_SET_HIGH: 665 lbs_deb_enter(LBS_DEB_CMD);
641 prtp->action = cpu_to_le16(CMD_ACT_SET);
642 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
643 break;
644 666
645 case CMD_ACT_TX_POWER_OPT_SET_MID: 667 memset(&cmd, 0, sizeof(cmd));
646 prtp->action = cpu_to_le16(CMD_ACT_SET); 668 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
647 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID); 669 cmd.action = cpu_to_le16(CMD_ACT_SET);
648 break; 670 cmd.curlevel = cpu_to_le16(dbm);
649 671
650 case CMD_ACT_TX_POWER_OPT_SET_LOW: 672 lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
651 prtp->action = cpu_to_le16(CMD_ACT_SET); 673
652 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf)); 674 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
653 break;
654 }
655 675
656 lbs_deb_leave(LBS_DEB_CMD); 676 lbs_deb_leave(LBS_DEB_CMD);
657 return 0; 677 return ret;
658} 678}
659 679
660static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, 680static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
@@ -1420,11 +1440,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1420 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); 1440 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
1421 break; 1441 break;
1422 1442
1423 case CMD_802_11_RF_TX_POWER:
1424 ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
1425 cmd_action, pdata_buf);
1426 break;
1427
1428 case CMD_802_11_MONITOR_MODE: 1443 case CMD_802_11_MONITOR_MODE:
1429 ret = lbs_cmd_802_11_monitor_mode(cmdptr, 1444 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
1430 cmd_action, pdata_buf); 1445 cmd_action, pdata_buf);
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index a53b51f8bdb4..6fba8ef7d09a 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -61,4 +61,8 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
61int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, 61int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
62 struct assoc_request *assoc); 62 struct assoc_request *assoc);
63 63
64int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
65 s16 *maxlevel);
66int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
67
64#endif /* _LBS_CMD_H */ 68#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 24de3c3cf877..dfaf03a4bbba 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -188,21 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
188 return 0; 188 return 0;
189} 189}
190 190
191static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
192 struct cmd_ds_command *resp)
193{
194 struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
195
196 lbs_deb_enter(LBS_DEB_CMD);
197
198 priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
199
200 lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
201
202 lbs_deb_leave(LBS_DEB_CMD);
203 return 0;
204}
205
206static int lbs_ret_802_11_rssi(struct lbs_private *priv, 191static int lbs_ret_802_11_rssi(struct lbs_private *priv,
207 struct cmd_ds_command *resp) 192 struct cmd_ds_command *resp)
208{ 193{
@@ -287,10 +272,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
287 ret = lbs_ret_802_11_snmp_mib(priv, resp); 272 ret = lbs_ret_802_11_snmp_mib(priv, resp);
288 break; 273 break;
289 274
290 case CMD_RET(CMD_802_11_RF_TX_POWER):
291 ret = lbs_ret_802_11_rf_tx_power(priv, resp);
292 break;
293
294 case CMD_RET(CMD_802_11_SET_AFC): 275 case CMD_RET(CMD_802_11_SET_AFC):
295 case CMD_RET(CMD_802_11_GET_AFC): 276 case CMD_RET(CMD_802_11_GET_AFC):
296 spin_lock_irqsave(&priv->driver_lock, flags); 277 spin_lock_irqsave(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f5bb40c54d85..560d4d3db66b 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -253,7 +253,9 @@ struct lbs_private {
253 u32 connect_status; 253 u32 connect_status;
254 u32 mesh_connect_status; 254 u32 mesh_connect_status;
255 u16 regioncode; 255 u16 regioncode;
256 u16 txpowerlevel; 256 s16 txpower_cur;
257 s16 txpower_min;
258 s16 txpower_max;
257 259
258 /** POWER MANAGEMENT AND PnP SUPPORT */ 260 /** POWER MANAGEMENT AND PnP SUPPORT */
259 u8 surpriseremoved; 261 u8 surpriseremoved;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c92e41b4faf4..413030f17d74 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -178,16 +178,6 @@
178#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 178#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
179#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 179#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
180 180
181/* Define action or option for CMD_802_11_RF_TX_POWER */
182#define CMD_ACT_TX_POWER_OPT_GET 0x0000
183#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
184#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
185#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
186
187#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
188#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
189#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
190
191/* Define action or option for CMD_802_11_DATA_RATE */ 181/* Define action or option for CMD_802_11_DATA_RATE */
192#define CMD_ACT_SET_TX_AUTO 0x0000 182#define CMD_ACT_SET_TX_AUTO 0x0000
193#define CMD_ACT_SET_TX_FIX_RATE 0x0001 183#define CMD_ACT_SET_TX_FIX_RATE 0x0001
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 913b480211a9..7f155cd1c117 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -435,8 +435,12 @@ struct cmd_ds_802_11_mac_address {
435}; 435};
436 436
437struct cmd_ds_802_11_rf_tx_power { 437struct cmd_ds_802_11_rf_tx_power {
438 struct cmd_header hdr;
439
438 __le16 action; 440 __le16 action;
439 __le16 currentlevel; 441 __le16 curlevel;
442 s8 maxlevel;
443 s8 minlevel;
440}; 444};
441 445
442struct cmd_ds_802_11_rf_antenna { 446struct cmd_ds_802_11_rf_antenna {
@@ -701,7 +705,6 @@ struct cmd_ds_command {
701 struct cmd_ds_802_11_get_stat gstat; 705 struct cmd_ds_802_11_get_stat gstat;
702 struct cmd_ds_802_3_get_stat gstat_8023; 706 struct cmd_ds_802_3_get_stat gstat_8023;
703 struct cmd_ds_802_11_snmp_mib smib; 707 struct cmd_ds_802_11_snmp_mib smib;
704 struct cmd_ds_802_11_rf_tx_power txp;
705 struct cmd_ds_802_11_rf_antenna rant; 708 struct cmd_ds_802_11_rf_antenna rant;
706 struct cmd_ds_802_11_monitor_mode monitor; 709 struct cmd_ds_802_11_monitor_mode monitor;
707 struct cmd_ds_802_11_ad_hoc_join adj; 710 struct cmd_ds_802_11_ad_hoc_join adj;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index bd32ac0b4e07..3c13619ffa15 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -956,17 +956,24 @@ EXPORT_SYMBOL_GPL(lbs_resume);
956static int lbs_setup_firmware(struct lbs_private *priv) 956static int lbs_setup_firmware(struct lbs_private *priv)
957{ 957{
958 int ret = -1; 958 int ret = -1;
959 s16 curlevel = 0, minlevel = 0, maxlevel = 0;
959 960
960 lbs_deb_enter(LBS_DEB_FW); 961 lbs_deb_enter(LBS_DEB_FW);
961 962
962 /* 963 /* Read MAC address from firmware */
963 * Read MAC address from HW
964 */
965 memset(priv->current_addr, 0xff, ETH_ALEN); 964 memset(priv->current_addr, 0xff, ETH_ALEN);
966 ret = lbs_update_hw_spec(priv); 965 ret = lbs_update_hw_spec(priv);
967 if (ret) 966 if (ret)
968 goto done; 967 goto done;
969 968
969 /* Read power levels if available */
970 ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
971 if (ret == 0) {
972 priv->txpower_cur = curlevel;
973 priv->txpower_min = minlevel;
974 priv->txpower_max = maxlevel;
975 }
976
970 lbs_set_mac_control(priv); 977 lbs_set_mac_control(priv);
971done: 978done:
972 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 979 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 8b3ed77860b3..10a806666001 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -422,26 +422,24 @@ static int lbs_get_txpow(struct net_device *dev,
422{ 422{
423 int ret = 0; 423 int ret = 0;
424 struct lbs_private *priv = dev->priv; 424 struct lbs_private *priv = dev->priv;
425 s16 curlevel = 0;
425 426
426 lbs_deb_enter(LBS_DEB_WEXT); 427 lbs_deb_enter(LBS_DEB_WEXT);
427 428
428 ret = lbs_prepare_and_send_command(priv, 429 ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
429 CMD_802_11_RF_TX_POWER,
430 CMD_ACT_TX_POWER_OPT_GET,
431 CMD_OPTION_WAITFORRSP, 0, NULL);
432
433 if (ret) 430 if (ret)
434 goto out; 431 goto out;
435 432
436 lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel); 433 lbs_deb_wext("tx power level %d dbm\n", curlevel);
437 vwrq->value = priv->txpowerlevel; 434
435 priv->txpower_cur = curlevel;
436 vwrq->value = curlevel;
438 vwrq->fixed = 1; 437 vwrq->fixed = 1;
439 if (priv->radioon) { 438 if (priv->radioon) {
440 vwrq->disabled = 0; 439 vwrq->disabled = 0;
441 vwrq->flags = IW_TXPOW_DBM; 440 vwrq->flags = IW_TXPOW_DBM;
442 } else { 441 } else
443 vwrq->disabled = 1; 442 vwrq->disabled = 1;
444 }
445 443
446out: 444out:
447 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 445 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
@@ -693,22 +691,12 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
693 691
694 range->sensitivity = 0; 692 range->sensitivity = 0;
695 693
696 /* 694 /* Setup the supported power level ranges */
697 * Setup the supported power level ranges
698 */
699 memset(range->txpower, 0, sizeof(range->txpower)); 695 memset(range->txpower, 0, sizeof(range->txpower));
700 range->txpower[0] = 5; 696 range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
701 range->txpower[1] = 7; 697 range->txpower[0] = priv->txpower_min;
702 range->txpower[2] = 9; 698 range->txpower[1] = priv->txpower_max;
703 range->txpower[3] = 11; 699 range->num_txpower = 2;
704 range->txpower[4] = 13;
705 range->txpower[5] = 15;
706 range->txpower[6] = 17;
707 range->txpower[7] = 19;
708
709 range->num_txpower = 8;
710 range->txpower_capa = IW_TXPOW_DBM;
711 range->txpower_capa |= IW_TXPOW_RANGE;
712 700
713 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | 701 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
714 IW_EVENT_CAPA_MASK(SIOCGIWAP) | 702 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
@@ -1844,39 +1832,46 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
1844{ 1832{
1845 int ret = 0; 1833 int ret = 0;
1846 struct lbs_private *priv = dev->priv; 1834 struct lbs_private *priv = dev->priv;
1847 1835 s16 dbm = (s16) vwrq->value;
1848 u16 dbm;
1849 1836
1850 lbs_deb_enter(LBS_DEB_WEXT); 1837 lbs_deb_enter(LBS_DEB_WEXT);
1851 1838
1852 if (vwrq->disabled) { 1839 if (vwrq->disabled) {
1853 lbs_radio_ioctl(priv, RADIO_OFF); 1840 lbs_radio_ioctl(priv, RADIO_OFF);
1854 return 0; 1841 goto out;
1855 } 1842 }
1856 1843
1857 priv->preamble = CMD_TYPE_AUTO_PREAMBLE; 1844 if (vwrq->fixed == 0) {
1858 1845 /* Auto power control */
1859 lbs_radio_ioctl(priv, RADIO_ON); 1846 priv->preamble = CMD_TYPE_AUTO_PREAMBLE;
1847 dbm = priv->txpower_max;
1848 } else {
1849 /* Userspace check in iwrange if it should use dBm or mW,
1850 * therefore this should never happen... Jean II */
1851 if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
1852 ret = -EOPNOTSUPP;
1853 goto out;
1854 }
1860 1855
1861 /* Userspace check in iwrange if it should use dBm or mW, 1856 /* Validate requested power level against firmware allowed levels */
1862 * therefore this should never happen... Jean II */ 1857 if (priv->txpower_min && (dbm < priv->txpower_min)) {
1863 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) { 1858 ret = -EINVAL;
1864 return -EOPNOTSUPP; 1859 goto out;
1865 } else 1860 }
1866 dbm = (u16) vwrq->value;
1867 1861
1868 /* auto tx power control */ 1862 if (priv->txpower_max && (dbm > priv->txpower_max)) {
1863 ret = -EINVAL;
1864 goto out;
1865 }
1866 }
1869 1867
1870 if (vwrq->fixed == 0) 1868 lbs_radio_ioctl(priv, RADIO_ON);
1871 dbm = 0xffff;
1872 1869
1873 lbs_deb_wext("txpower set %d dbm\n", dbm); 1870 lbs_deb_wext("txpower set %d dBm\n", dbm);
1874 1871
1875 ret = lbs_prepare_and_send_command(priv, 1872 ret = lbs_set_tx_power(priv, dbm);
1876 CMD_802_11_RF_TX_POWER,
1877 CMD_ACT_TX_POWER_OPT_SET_LOW,
1878 CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
1879 1873
1874out:
1880 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1875 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1881 return ret; 1876 return ret;
1882} 1877}