aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r--drivers/net/wireless/libertas/cmd.c192
1 files changed, 104 insertions, 88 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 8124fd9b1353..75427e61898d 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <net/iw_handler.h> 6#include <net/iw_handler.h>
7#include <net/ieee80211.h>
7#include <linux/kfifo.h> 8#include <linux/kfifo.h>
8#include "host.h" 9#include "host.h"
9#include "hostcmd.h" 10#include "hostcmd.h"
@@ -109,7 +110,7 @@ int lbs_update_hw_spec(struct lbs_private *priv)
109 * CF card firmware 5.0.16p0: cap 0x00000303 110 * CF card firmware 5.0.16p0: cap 0x00000303
110 * USB dongle firmware 5.110.17p2: cap 0x00000303 111 * USB dongle firmware 5.110.17p2: cap 0x00000303
111 */ 112 */
112 printk("libertas: %s, fw %u.%u.%up%u, cap 0x%08x\n", 113 lbs_pr_info("%s, fw %u.%u.%up%u, cap 0x%08x\n",
113 print_mac(mac, cmd.permanentaddr), 114 print_mac(mac, cmd.permanentaddr),
114 priv->fwrelease >> 24 & 0xff, 115 priv->fwrelease >> 24 & 0xff,
115 priv->fwrelease >> 16 & 0xff, 116 priv->fwrelease >> 16 & 0xff,
@@ -675,58 +676,60 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
675 return 0; 676 return 0;
676} 677}
677 678
678static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, 679static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
679 struct cmd_ds_command *cmd,
680 u16 cmd_action)
681{ 680{
682 struct cmd_ds_802_11_rate_adapt_rateset 681/* Bit Rate
683 *rateadapt = &cmd->params.rateset; 682* 15:13 Reserved
684 683* 12 54 Mbps
685 lbs_deb_enter(LBS_DEB_CMD); 684* 11 48 Mbps
686 cmd->size = 685* 10 36 Mbps
687 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset) 686* 9 24 Mbps
688 + S_DS_GEN); 687* 8 18 Mbps
689 cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET); 688* 7 12 Mbps
690 689* 6 9 Mbps
691 rateadapt->action = cpu_to_le16(cmd_action); 690* 5 6 Mbps
692 rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto); 691* 4 Reserved
693 rateadapt->bitmap = cpu_to_le16(priv->ratebitmap); 692* 3 11 Mbps
694 693* 2 5.5 Mbps
695 lbs_deb_leave(LBS_DEB_CMD); 694* 1 2 Mbps
696 return 0; 695* 0 1 Mbps
696**/
697
698 uint16_t ratemask;
699 int i = lbs_data_rate_to_fw_index(rate);
700 if (lower_rates_ok)
701 ratemask = (0x1fef >> (12 - i));
702 else
703 ratemask = (1 << i);
704 return cpu_to_le16(ratemask);
697} 705}
698 706
699/** 707int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
700 * @brief Get the current data rate 708 uint16_t cmd_action)
701 *
702 * @param priv A pointer to struct lbs_private structure
703 *
704 * @return The data rate on success, error on failure
705 */
706int lbs_get_data_rate(struct lbs_private *priv)
707{ 709{
708 struct cmd_ds_802_11_data_rate cmd; 710 struct cmd_ds_802_11_rate_adapt_rateset cmd;
709 int ret = -1; 711 int ret;
710 712
711 lbs_deb_enter(LBS_DEB_CMD); 713 lbs_deb_enter(LBS_DEB_CMD);
712 714
713 memset(&cmd, 0, sizeof(cmd)); 715 if (!priv->cur_rate && !priv->enablehwauto)
714 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 716 return -EINVAL;
715 cmd.action = cpu_to_le16(CMD_ACT_GET_TX_RATE);
716
717 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
718 if (ret)
719 goto out;
720 717
721 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); 718 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
722 719
723 ret = (int) lbs_fw_index_to_data_rate(cmd.rates[0]); 720 cmd.action = cpu_to_le16(cmd_action);
724 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", ret); 721 cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
722 cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
723 ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
724 if (!ret && cmd_action == CMD_ACT_GET) {
725 priv->ratebitmap = le16_to_cpu(cmd.bitmap);
726 priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
727 }
725 728
726out:
727 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 729 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
728 return ret; 730 return ret;
729} 731}
732EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset);
730 733
731/** 734/**
732 * @brief Set the data rate 735 * @brief Set the data rate
@@ -778,28 +781,6 @@ out:
778 return ret; 781 return ret;
779} 782}
780 783
781static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv,
782 struct cmd_ds_command *cmd,
783 u16 cmd_action)
784{
785 struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
786
787 lbs_deb_enter(LBS_DEB_CMD);
788 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
789 S_DS_GEN);
790 cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
791
792 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
793 pMCastAdr->action = cpu_to_le16(cmd_action);
794 pMCastAdr->nr_of_adrs =
795 cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
796 memcpy(pMCastAdr->maclist, priv->multicastlist,
797 priv->nr_of_multicastmacaddr * ETH_ALEN);
798
799 lbs_deb_leave(LBS_DEB_CMD);
800 return 0;
801}
802
803/** 784/**
804 * @brief Get the radio channel 785 * @brief Get the radio channel
805 * 786 *
@@ -1052,24 +1033,69 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
1052 return ret; 1033 return ret;
1053} 1034}
1054 1035
1055int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan) 1036int lbs_mesh_config_send(struct lbs_private *priv,
1037 struct cmd_ds_mesh_config *cmd,
1038 uint16_t action, uint16_t type)
1039{
1040 int ret;
1041
1042 lbs_deb_enter(LBS_DEB_CMD);
1043
1044 cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
1045 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
1046 cmd->hdr.result = 0;
1047
1048 cmd->type = cpu_to_le16(type);
1049 cmd->action = cpu_to_le16(action);
1050
1051 ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd);
1052
1053 lbs_deb_leave(LBS_DEB_CMD);
1054 return ret;
1055}
1056
1057/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
1058 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
1059 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
1060 * lbs_mesh_config_send.
1061 */
1062int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
1056{ 1063{
1057 struct cmd_ds_mesh_config cmd; 1064 struct cmd_ds_mesh_config cmd;
1065 struct mrvl_meshie *ie;
1058 1066
1059 memset(&cmd, 0, sizeof(cmd)); 1067 memset(&cmd, 0, sizeof(cmd));
1060 cmd.action = cpu_to_le16(enable);
1061 cmd.channel = cpu_to_le16(chan); 1068 cmd.channel = cpu_to_le16(chan);
1062 cmd.type = cpu_to_le16(priv->mesh_tlv); 1069 ie = (struct mrvl_meshie *)cmd.data;
1063 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1070
1064 1071 switch (action) {
1065 if (enable) { 1072 case CMD_ACT_MESH_CONFIG_START:
1066 cmd.length = cpu_to_le16(priv->mesh_ssid_len); 1073 ie->hdr.id = MFIE_TYPE_GENERIC;
1067 memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len); 1074 ie->val.oui[0] = 0x00;
1075 ie->val.oui[1] = 0x50;
1076 ie->val.oui[2] = 0x43;
1077 ie->val.type = MARVELL_MESH_IE_TYPE;
1078 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
1079 ie->val.version = MARVELL_MESH_IE_VERSION;
1080 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
1081 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
1082 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
1083 ie->val.mesh_id_len = priv->mesh_ssid_len;
1084 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
1085 ie->hdr.len = sizeof(struct mrvl_meshie_val) -
1086 IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
1087 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
1088 break;
1089 case CMD_ACT_MESH_CONFIG_STOP:
1090 break;
1091 default:
1092 return -1;
1068 } 1093 }
1069 lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n", 1094 lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
1070 enable, priv->mesh_tlv, chan, 1095 action, priv->mesh_tlv, chan,
1071 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); 1096 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
1072 return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd); 1097
1098 return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
1073} 1099}
1074 1100
1075static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, 1101static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
@@ -1144,7 +1170,7 @@ static void lbs_submit_command(struct lbs_private *priv,
1144 struct cmd_header *cmd; 1170 struct cmd_header *cmd;
1145 uint16_t cmdsize; 1171 uint16_t cmdsize;
1146 uint16_t command; 1172 uint16_t command;
1147 int timeo = 5 * HZ; 1173 int timeo = 3 * HZ;
1148 int ret; 1174 int ret;
1149 1175
1150 lbs_deb_enter(LBS_DEB_HOST); 1176 lbs_deb_enter(LBS_DEB_HOST);
@@ -1162,7 +1188,7 @@ static void lbs_submit_command(struct lbs_private *priv,
1162 /* These commands take longer */ 1188 /* These commands take longer */
1163 if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE || 1189 if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
1164 command == CMD_802_11_AUTHENTICATE) 1190 command == CMD_802_11_AUTHENTICATE)
1165 timeo = 10 * HZ; 1191 timeo = 5 * HZ;
1166 1192
1167 lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", 1193 lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
1168 command, le16_to_cpu(cmd->seqnum), cmdsize); 1194 command, le16_to_cpu(cmd->seqnum), cmdsize);
@@ -1174,7 +1200,7 @@ static void lbs_submit_command(struct lbs_private *priv,
1174 lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); 1200 lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
1175 /* Let the timer kick in and retry, and potentially reset 1201 /* Let the timer kick in and retry, and potentially reset
1176 the whole thing if the condition persists */ 1202 the whole thing if the condition persists */
1177 timeo = HZ; 1203 timeo = HZ/4;
1178 } 1204 }
1179 1205
1180 /* Setup the timer after transmit command */ 1206 /* Setup the timer after transmit command */
@@ -1279,8 +1305,7 @@ void lbs_set_mac_control(struct lbs_private *priv)
1279 cmd.action = cpu_to_le16(priv->mac_control); 1305 cmd.action = cpu_to_le16(priv->mac_control);
1280 cmd.reserved = 0; 1306 cmd.reserved = 0;
1281 1307
1282 lbs_cmd_async(priv, CMD_MAC_CONTROL, 1308 lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
1283 &cmd.hdr, sizeof(cmd));
1284 1309
1285 lbs_deb_leave(LBS_DEB_CMD); 1310 lbs_deb_leave(LBS_DEB_CMD);
1286} 1311}
@@ -1387,15 +1412,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1387 cmd_action, pdata_buf); 1412 cmd_action, pdata_buf);
1388 break; 1413 break;
1389 1414
1390 case CMD_802_11_RATE_ADAPT_RATESET:
1391 ret = lbs_cmd_802_11_rate_adapt_rateset(priv,
1392 cmdptr, cmd_action);
1393 break;
1394
1395 case CMD_MAC_MULTICAST_ADR:
1396 ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1397 break;
1398
1399 case CMD_802_11_MONITOR_MODE: 1415 case CMD_802_11_MONITOR_MODE:
1400 ret = lbs_cmd_802_11_monitor_mode(cmdptr, 1416 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
1401 cmd_action, pdata_buf); 1417 cmd_action, pdata_buf);
@@ -1484,7 +1500,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1484 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); 1500 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1485 break; 1501 break;
1486 default: 1502 default:
1487 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no); 1503 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1488 ret = -1; 1504 ret = -1;
1489 break; 1505 break;
1490 } 1506 }