diff options
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 192 |
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 | ||
678 | static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | 679 | static __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 | /** | 707 | int 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 | */ | ||
706 | int 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 | ||
726 | out: | ||
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 | } |
732 | EXPORT_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 | ||
781 | static 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 | ||
1055 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan) | 1036 | int 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 | */ | ||
1062 | int 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 | ||
1075 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, | 1101 | static 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 | } |