diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-10 04:54:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-10 04:54:31 -0400 |
commit | 788c0a53164c05c5ccdb1472474372b72ba74644 (patch) | |
tree | 5f274102e3dc4bcca6cb3a695aa2c8228ad5fc4f /drivers/net/wireless/libertas | |
parent | e64bda89b8fe81cce9b4a20885d2c204c2d52532 (diff) | |
parent | 78cf07472f0ede8394bacc4bc02354505080cfe1 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
drivers/net/ps3_gelic_wireless.c
drivers/net/wireless/libertas/main.c
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r-- | drivers/net/wireless/libertas/Makefile | 8 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/assoc.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmd.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/defs.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/host.h | 17 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/hostcmd.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 227 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 216 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/persistcfg.c | 453 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/rx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/types.h | 30 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/wext.c | 32 |
17 files changed, 930 insertions, 321 deletions
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index f0724e31adfd..02080a3682a9 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -1,9 +1,5 @@ | |||
1 | libertas-objs := main.o wext.o \ | 1 | libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ |
2 | rx.o tx.o cmd.o \ | 2 | debugfs.o persistcfg.o ethtool.o assoc.o |
3 | cmdresp.o scan.o \ | ||
4 | 11d.o \ | ||
5 | debugfs.o \ | ||
6 | ethtool.o assoc.o | ||
7 | 3 | ||
8 | usb8xxx-objs += if_usb.o | 4 | usb8xxx-objs += if_usb.o |
9 | libertas_cs-objs += if_cs.o | 5 | libertas_cs-objs += if_cs.o |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index c9c3640ce9fb..a267d6e65f03 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -603,7 +603,8 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
603 | /* Change mesh channel first; 21.p21 firmware won't let | 603 | /* Change mesh channel first; 21.p21 firmware won't let |
604 | you change channel otherwise (even though it'll return | 604 | you change channel otherwise (even though it'll return |
605 | an error to this */ | 605 | an error to this */ |
606 | lbs_mesh_config(priv, 0, assoc_req->channel); | 606 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, |
607 | assoc_req->channel); | ||
607 | } | 608 | } |
608 | 609 | ||
609 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", | 610 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", |
@@ -642,7 +643,8 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
642 | 643 | ||
643 | restore_mesh: | 644 | restore_mesh: |
644 | if (priv->mesh_dev) | 645 | if (priv->mesh_dev) |
645 | lbs_mesh_config(priv, 1, priv->curbssparams.channel); | 646 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
647 | priv->curbssparams.channel); | ||
646 | 648 | ||
647 | done: | 649 | done: |
648 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 650 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -1248,7 +1250,7 @@ static int get_common_rates(struct lbs_private *priv, | |||
1248 | lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); | 1250 | lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); |
1249 | lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); | 1251 | lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); |
1250 | 1252 | ||
1251 | if (!priv->auto_rate) { | 1253 | if (!priv->enablehwauto) { |
1252 | for (i = 0; i < tmp_size; i++) { | 1254 | for (i = 0; i < tmp_size; i++) { |
1253 | if (tmp[i] == priv->cur_rate) | 1255 | if (tmp[i] == priv->cur_rate) |
1254 | goto done; | 1256 | goto done; |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index c2dd43ece069..cf261d3487fd 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,26 +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 |
683 | * 12 54 Mbps | ||
684 | * 11 48 Mbps | ||
685 | * 10 36 Mbps | ||
686 | * 9 24 Mbps | ||
687 | * 8 18 Mbps | ||
688 | * 7 12 Mbps | ||
689 | * 6 9 Mbps | ||
690 | * 5 6 Mbps | ||
691 | * 4 Reserved | ||
692 | * 3 11 Mbps | ||
693 | * 2 5.5 Mbps | ||
694 | * 1 2 Mbps | ||
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); | ||
705 | } | ||
706 | |||
707 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
708 | uint16_t cmd_action) | ||
709 | { | ||
710 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
711 | int ret; | ||
684 | 712 | ||
685 | lbs_deb_enter(LBS_DEB_CMD); | 713 | lbs_deb_enter(LBS_DEB_CMD); |
686 | cmd->size = | ||
687 | cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset) | ||
688 | + S_DS_GEN); | ||
689 | cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET); | ||
690 | 714 | ||
691 | rateadapt->action = cpu_to_le16(cmd_action); | 715 | if (!priv->cur_rate && !priv->enablehwauto) |
692 | rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto); | 716 | return -EINVAL; |
693 | rateadapt->bitmap = cpu_to_le16(priv->ratebitmap); | ||
694 | 717 | ||
695 | lbs_deb_leave(LBS_DEB_CMD); | 718 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
696 | return 0; | 719 | |
720 | cmd.action = cpu_to_le16(cmd_action); | ||
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 | } | ||
728 | |||
729 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
730 | return ret; | ||
697 | } | 731 | } |
732 | EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset); | ||
698 | 733 | ||
699 | /** | 734 | /** |
700 | * @brief Set the data rate | 735 | * @brief Set the data rate |
@@ -746,28 +781,6 @@ out: | |||
746 | return ret; | 781 | return ret; |
747 | } | 782 | } |
748 | 783 | ||
749 | static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv, | ||
750 | struct cmd_ds_command *cmd, | ||
751 | u16 cmd_action) | ||
752 | { | ||
753 | struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr; | ||
754 | |||
755 | lbs_deb_enter(LBS_DEB_CMD); | ||
756 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + | ||
757 | S_DS_GEN); | ||
758 | cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR); | ||
759 | |||
760 | lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs); | ||
761 | pMCastAdr->action = cpu_to_le16(cmd_action); | ||
762 | pMCastAdr->nr_of_adrs = | ||
763 | cpu_to_le16((u16) priv->nr_of_multicastmacaddr); | ||
764 | memcpy(pMCastAdr->maclist, priv->multicastlist, | ||
765 | priv->nr_of_multicastmacaddr * ETH_ALEN); | ||
766 | |||
767 | lbs_deb_leave(LBS_DEB_CMD); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | /** | 784 | /** |
772 | * @brief Get the radio channel | 785 | * @brief Get the radio channel |
773 | * | 786 | * |
@@ -1020,24 +1033,69 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | |||
1020 | return ret; | 1033 | return ret; |
1021 | } | 1034 | } |
1022 | 1035 | ||
1023 | 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) | ||
1024 | { | 1063 | { |
1025 | struct cmd_ds_mesh_config cmd; | 1064 | struct cmd_ds_mesh_config cmd; |
1065 | struct mrvl_meshie *ie; | ||
1026 | 1066 | ||
1027 | memset(&cmd, 0, sizeof(cmd)); | 1067 | memset(&cmd, 0, sizeof(cmd)); |
1028 | cmd.action = cpu_to_le16(enable); | ||
1029 | cmd.channel = cpu_to_le16(chan); | 1068 | cmd.channel = cpu_to_le16(chan); |
1030 | cmd.type = cpu_to_le16(priv->mesh_tlv); | 1069 | ie = (struct mrvl_meshie *)cmd.data; |
1031 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 1070 | |
1032 | 1071 | switch (action) { | |
1033 | if (enable) { | 1072 | case CMD_ACT_MESH_CONFIG_START: |
1034 | cmd.length = cpu_to_le16(priv->mesh_ssid_len); | 1073 | ie->hdr.id = MFIE_TYPE_GENERIC; |
1035 | 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; | ||
1036 | } | 1093 | } |
1037 | 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", |
1038 | enable, priv->mesh_tlv, chan, | 1095 | action, priv->mesh_tlv, chan, |
1039 | escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); | 1096 | escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); |
1040 | return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd); | 1097 | |
1098 | return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | ||
1041 | } | 1099 | } |
1042 | 1100 | ||
1043 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, | 1101 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, |
@@ -1112,7 +1170,7 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1112 | struct cmd_header *cmd; | 1170 | struct cmd_header *cmd; |
1113 | uint16_t cmdsize; | 1171 | uint16_t cmdsize; |
1114 | uint16_t command; | 1172 | uint16_t command; |
1115 | int timeo = 5 * HZ; | 1173 | int timeo = 3 * HZ; |
1116 | int ret; | 1174 | int ret; |
1117 | 1175 | ||
1118 | lbs_deb_enter(LBS_DEB_HOST); | 1176 | lbs_deb_enter(LBS_DEB_HOST); |
@@ -1130,7 +1188,7 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1130 | /* These commands take longer */ | 1188 | /* These commands take longer */ |
1131 | if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE || | 1189 | if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE || |
1132 | command == CMD_802_11_AUTHENTICATE) | 1190 | command == CMD_802_11_AUTHENTICATE) |
1133 | timeo = 10 * HZ; | 1191 | timeo = 5 * HZ; |
1134 | 1192 | ||
1135 | 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", |
1136 | command, le16_to_cpu(cmd->seqnum), cmdsize); | 1194 | command, le16_to_cpu(cmd->seqnum), cmdsize); |
@@ -1142,7 +1200,7 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1142 | 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); |
1143 | /* Let the timer kick in and retry, and potentially reset | 1201 | /* Let the timer kick in and retry, and potentially reset |
1144 | the whole thing if the condition persists */ | 1202 | the whole thing if the condition persists */ |
1145 | timeo = HZ; | 1203 | timeo = HZ/4; |
1146 | } | 1204 | } |
1147 | 1205 | ||
1148 | /* Setup the timer after transmit command */ | 1206 | /* Setup the timer after transmit command */ |
@@ -1247,8 +1305,7 @@ void lbs_set_mac_control(struct lbs_private *priv) | |||
1247 | cmd.action = cpu_to_le16(priv->mac_control); | 1305 | cmd.action = cpu_to_le16(priv->mac_control); |
1248 | cmd.reserved = 0; | 1306 | cmd.reserved = 0; |
1249 | 1307 | ||
1250 | lbs_cmd_async(priv, CMD_MAC_CONTROL, | 1308 | lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd)); |
1251 | &cmd.hdr, sizeof(cmd)); | ||
1252 | 1309 | ||
1253 | lbs_deb_leave(LBS_DEB_CMD); | 1310 | lbs_deb_leave(LBS_DEB_CMD); |
1254 | } | 1311 | } |
@@ -1355,15 +1412,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1355 | cmd_action, pdata_buf); | 1412 | cmd_action, pdata_buf); |
1356 | break; | 1413 | break; |
1357 | 1414 | ||
1358 | case CMD_802_11_RATE_ADAPT_RATESET: | ||
1359 | ret = lbs_cmd_802_11_rate_adapt_rateset(priv, | ||
1360 | cmdptr, cmd_action); | ||
1361 | break; | ||
1362 | |||
1363 | case CMD_MAC_MULTICAST_ADR: | ||
1364 | ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action); | ||
1365 | break; | ||
1366 | |||
1367 | case CMD_802_11_MONITOR_MODE: | 1415 | case CMD_802_11_MONITOR_MODE: |
1368 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, | 1416 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, |
1369 | cmd_action, pdata_buf); | 1417 | cmd_action, pdata_buf); |
@@ -1452,7 +1500,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1452 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1500 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1453 | break; | 1501 | break; |
1454 | default: | 1502 | default: |
1455 | 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); |
1456 | ret = -1; | 1504 | ret = -1; |
1457 | break; | 1505 | break; |
1458 | } | 1506 | } |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index f4019c22adfc..a53b51f8bdb4 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -39,12 +39,17 @@ int lbs_set_data_rate(struct lbs_private *priv, u8 rate); | |||
39 | int lbs_get_channel(struct lbs_private *priv); | 39 | int lbs_get_channel(struct lbs_private *priv); |
40 | int lbs_set_channel(struct lbs_private *priv, u8 channel); | 40 | int lbs_set_channel(struct lbs_private *priv, u8 channel); |
41 | 41 | ||
42 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
43 | struct cmd_ds_mesh_config *cmd, | ||
44 | uint16_t action, uint16_t type); | ||
42 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | 45 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); |
43 | 46 | ||
44 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); | 47 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); |
45 | int lbs_suspend(struct lbs_private *priv); | 48 | int lbs_suspend(struct lbs_private *priv); |
46 | void lbs_resume(struct lbs_private *priv); | 49 | void lbs_resume(struct lbs_private *priv); |
47 | 50 | ||
51 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
52 | uint16_t cmd_action); | ||
48 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | 53 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, |
49 | uint16_t cmd_action, uint16_t *timeout); | 54 | uint16_t cmd_action, uint16_t *timeout); |
50 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 55 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 5abecb7673e6..24de3c3cf877 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -203,22 +203,6 @@ static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv, | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
207 | struct cmd_ds_command *resp) | ||
208 | { | ||
209 | struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset; | ||
210 | |||
211 | lbs_deb_enter(LBS_DEB_CMD); | ||
212 | |||
213 | if (rates->action == CMD_ACT_GET) { | ||
214 | priv->enablehwauto = le16_to_cpu(rates->enablehwauto); | ||
215 | priv->ratebitmap = le16_to_cpu(rates->bitmap); | ||
216 | } | ||
217 | |||
218 | lbs_deb_leave(LBS_DEB_CMD); | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, | 206 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, |
223 | struct cmd_ds_command *resp) | 207 | struct cmd_ds_command *resp) |
224 | { | 208 | { |
@@ -316,16 +300,11 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
316 | 300 | ||
317 | break; | 301 | break; |
318 | 302 | ||
319 | case CMD_RET(CMD_MAC_MULTICAST_ADR): | ||
320 | case CMD_RET(CMD_802_11_RESET): | 303 | case CMD_RET(CMD_802_11_RESET): |
321 | case CMD_RET(CMD_802_11_AUTHENTICATE): | 304 | case CMD_RET(CMD_802_11_AUTHENTICATE): |
322 | case CMD_RET(CMD_802_11_BEACON_STOP): | 305 | case CMD_RET(CMD_802_11_BEACON_STOP): |
323 | break; | 306 | break; |
324 | 307 | ||
325 | case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET): | ||
326 | ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp); | ||
327 | break; | ||
328 | |||
329 | case CMD_RET(CMD_802_11_RSSI): | 308 | case CMD_RET(CMD_802_11_RSSI): |
330 | ret = lbs_ret_802_11_rssi(priv, resp); | 309 | ret = lbs_ret_802_11_rssi(priv, resp); |
331 | break; | 310 | break; |
@@ -376,8 +355,8 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
376 | break; | 355 | break; |
377 | 356 | ||
378 | default: | 357 | default: |
379 | lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n", | 358 | lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n", |
380 | le16_to_cpu(resp->command)); | 359 | le16_to_cpu(resp->command)); |
381 | break; | 360 | break; |
382 | } | 361 | } |
383 | lbs_deb_leave(LBS_DEB_HOST); | 362 | lbs_deb_leave(LBS_DEB_HOST); |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 0632b09655d2..a8ac974dacac 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -60,6 +60,10 @@ void lbs_mac_event_disconnected(struct lbs_private *priv); | |||
60 | 60 | ||
61 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); | 61 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); |
62 | 62 | ||
63 | /* persistcfg.c */ | ||
64 | void lbs_persist_config_init(struct net_device *net); | ||
65 | void lbs_persist_config_remove(struct net_device *net); | ||
66 | |||
63 | /* main.c */ | 67 | /* main.c */ |
64 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, | 68 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, |
65 | int *cfp_no); | 69 | int *cfp_no); |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index d39520111062..12e687550bce 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #define LBS_DEB_THREAD 0x00100000 | 40 | #define LBS_DEB_THREAD 0x00100000 |
41 | #define LBS_DEB_HEX 0x00200000 | 41 | #define LBS_DEB_HEX 0x00200000 |
42 | #define LBS_DEB_SDIO 0x00400000 | 42 | #define LBS_DEB_SDIO 0x00400000 |
43 | #define LBS_DEB_SYSFS 0x00800000 | ||
43 | 44 | ||
44 | extern unsigned int lbs_debug; | 45 | extern unsigned int lbs_debug; |
45 | 46 | ||
@@ -81,7 +82,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
81 | #define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args) | 82 | #define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args) |
82 | #define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args) | 83 | #define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args) |
83 | #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) | 84 | #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) |
84 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " thread", fmt, ##args) | 85 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) |
86 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) | ||
85 | 87 | ||
86 | #define lbs_pr_info(format, args...) \ | 88 | #define lbs_pr_info(format, args...) \ |
87 | printk(KERN_INFO DRV_NAME": " format, ## args) | 89 | printk(KERN_INFO DRV_NAME": " format, ## args) |
@@ -170,6 +172,16 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
170 | 172 | ||
171 | #define MARVELL_MESH_IE_LENGTH 9 | 173 | #define MARVELL_MESH_IE_LENGTH 9 |
172 | 174 | ||
175 | /* Values used to populate the struct mrvl_mesh_ie. The only time you need this | ||
176 | * is when enabling the mesh using CMD_MESH_CONFIG. | ||
177 | */ | ||
178 | #define MARVELL_MESH_IE_TYPE 4 | ||
179 | #define MARVELL_MESH_IE_SUBTYPE 0 | ||
180 | #define MARVELL_MESH_IE_VERSION 0 | ||
181 | #define MARVELL_MESH_PROTO_ID_HWMP 0 | ||
182 | #define MARVELL_MESH_METRIC_ID 0 | ||
183 | #define MARVELL_MESH_CAPABILITY 0 | ||
184 | |||
173 | /** INT status Bit Definition*/ | 185 | /** INT status Bit Definition*/ |
174 | #define MRVDRV_TX_DNLD_RDY 0x0001 | 186 | #define MRVDRV_TX_DNLD_RDY 0x0001 |
175 | #define MRVDRV_RX_UPLD_RDY 0x0002 | 187 | #define MRVDRV_RX_UPLD_RDY 0x0002 |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 0d9edb9b11f5..f5bb40c54d85 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -140,6 +140,8 @@ struct lbs_private { | |||
140 | wait_queue_head_t waitq; | 140 | wait_queue_head_t waitq; |
141 | struct workqueue_struct *work_thread; | 141 | struct workqueue_struct *work_thread; |
142 | 142 | ||
143 | struct work_struct mcast_work; | ||
144 | |||
143 | /** Scanning */ | 145 | /** Scanning */ |
144 | struct delayed_work scan_work; | 146 | struct delayed_work scan_work; |
145 | struct delayed_work assoc_work; | 147 | struct delayed_work assoc_work; |
@@ -151,6 +153,7 @@ struct lbs_private { | |||
151 | 153 | ||
152 | /** Hardware access */ | 154 | /** Hardware access */ |
153 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 155 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
156 | void (*reset_card) (struct lbs_private *priv); | ||
154 | 157 | ||
155 | /* Wake On LAN */ | 158 | /* Wake On LAN */ |
156 | uint32_t wol_criteria; | 159 | uint32_t wol_criteria; |
@@ -234,8 +237,8 @@ struct lbs_private { | |||
234 | /** 802.11 statistics */ | 237 | /** 802.11 statistics */ |
235 | // struct cmd_DS_802_11_GET_STAT wlan802_11Stat; | 238 | // struct cmd_DS_802_11_GET_STAT wlan802_11Stat; |
236 | 239 | ||
237 | u16 enablehwauto; | 240 | uint16_t enablehwauto; |
238 | u16 ratebitmap; | 241 | uint16_t ratebitmap; |
239 | 242 | ||
240 | u32 fragthsd; | 243 | u32 fragthsd; |
241 | u32 rtsthsd; | 244 | u32 rtsthsd; |
@@ -293,7 +296,6 @@ struct lbs_private { | |||
293 | 296 | ||
294 | /** data rate stuff */ | 297 | /** data rate stuff */ |
295 | u8 cur_rate; | 298 | u8 cur_rate; |
296 | u8 auto_rate; | ||
297 | 299 | ||
298 | /** RF calibration data */ | 300 | /** RF calibration data */ |
299 | 301 | ||
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 3915c3144fad..c92e41b4faf4 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -256,6 +256,23 @@ enum cmd_mesh_access_opts { | |||
256 | CMD_ACT_MESH_GET_AUTOSTART_ENABLED, | 256 | CMD_ACT_MESH_GET_AUTOSTART_ENABLED, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /* Define actions and types for CMD_MESH_CONFIG */ | ||
260 | enum cmd_mesh_config_actions { | ||
261 | CMD_ACT_MESH_CONFIG_STOP = 0, | ||
262 | CMD_ACT_MESH_CONFIG_START, | ||
263 | CMD_ACT_MESH_CONFIG_SET, | ||
264 | CMD_ACT_MESH_CONFIG_GET, | ||
265 | }; | ||
266 | |||
267 | enum cmd_mesh_config_types { | ||
268 | CMD_TYPE_MESH_SET_BOOTFLAG = 1, | ||
269 | CMD_TYPE_MESH_SET_BOOTTIME, | ||
270 | CMD_TYPE_MESH_SET_DEF_CHANNEL, | ||
271 | CMD_TYPE_MESH_SET_MESH_IE, | ||
272 | CMD_TYPE_MESH_GET_DEFAULTS, | ||
273 | CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */ | ||
274 | }; | ||
275 | |||
259 | /** Card Event definition */ | 276 | /** Card Event definition */ |
260 | #define MACREG_INT_CODE_TX_PPA_FREE 0 | 277 | #define MACREG_INT_CODE_TX_PPA_FREE 0 |
261 | #define MACREG_INT_CODE_TX_DMA_DONE 1 | 278 | #define MACREG_INT_CODE_TX_DMA_DONE 1 |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index f29bc5bbda3e..913b480211a9 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -219,6 +219,7 @@ struct cmd_ds_mac_control { | |||
219 | }; | 219 | }; |
220 | 220 | ||
221 | struct cmd_ds_mac_multicast_adr { | 221 | struct cmd_ds_mac_multicast_adr { |
222 | struct cmd_header hdr; | ||
222 | __le16 action; | 223 | __le16 action; |
223 | __le16 nr_of_adrs; | 224 | __le16 nr_of_adrs; |
224 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | 225 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; |
@@ -499,6 +500,7 @@ struct cmd_ds_802_11_data_rate { | |||
499 | }; | 500 | }; |
500 | 501 | ||
501 | struct cmd_ds_802_11_rate_adapt_rateset { | 502 | struct cmd_ds_802_11_rate_adapt_rateset { |
503 | struct cmd_header hdr; | ||
502 | __le16 action; | 504 | __le16 action; |
503 | __le16 enablehwauto; | 505 | __le16 enablehwauto; |
504 | __le16 bitmap; | 506 | __le16 bitmap; |
@@ -702,8 +704,6 @@ struct cmd_ds_command { | |||
702 | struct cmd_ds_802_11_rf_tx_power txp; | 704 | struct cmd_ds_802_11_rf_tx_power txp; |
703 | struct cmd_ds_802_11_rf_antenna rant; | 705 | struct cmd_ds_802_11_rf_antenna rant; |
704 | struct cmd_ds_802_11_monitor_mode monitor; | 706 | struct cmd_ds_802_11_monitor_mode monitor; |
705 | struct cmd_ds_802_11_rate_adapt_rateset rateset; | ||
706 | struct cmd_ds_mac_multicast_adr madr; | ||
707 | struct cmd_ds_802_11_ad_hoc_join adj; | 707 | struct cmd_ds_802_11_ad_hoc_join adj; |
708 | struct cmd_ds_802_11_rssi rssi; | 708 | struct cmd_ds_802_11_rssi rssi; |
709 | struct cmd_ds_802_11_rssi_rsp rssirsp; | 709 | struct cmd_ds_802_11_rssi_rsp rssirsp; |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 54280e292ea5..873ab10a0786 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -148,76 +148,72 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
148 | { | 148 | { |
149 | int i; | 149 | int i; |
150 | 150 | ||
151 | for (i = 0; i < 1000; i++) { | 151 | for (i = 0; i < 100000; i++) { |
152 | u8 val = if_cs_read8(card, addr); | 152 | u8 val = if_cs_read8(card, addr); |
153 | if (val == reg) | 153 | if (val == reg) |
154 | return i; | 154 | return i; |
155 | udelay(500); | 155 | udelay(5); |
156 | } | 156 | } |
157 | return -ETIME; | 157 | return -ETIME; |
158 | } | 158 | } |
159 | 159 | ||
160 | 160 | ||
161 | 161 | ||
162 | /* Host control registers and their bit definitions */ | 162 | /* First the bitmasks for the host/card interrupt/status registers: */ |
163 | #define IF_CS_BIT_TX 0x0001 | ||
164 | #define IF_CS_BIT_RX 0x0002 | ||
165 | #define IF_CS_BIT_COMMAND 0x0004 | ||
166 | #define IF_CS_BIT_RESP 0x0008 | ||
167 | #define IF_CS_BIT_EVENT 0x0010 | ||
168 | #define IF_CS_BIT_MASK 0x001f | ||
163 | 169 | ||
164 | #define IF_CS_H_STATUS 0x00000000 | 170 | /* And now the individual registers and assorted masks */ |
165 | #define IF_CS_H_STATUS_TX_OVER 0x0001 | 171 | #define IF_CS_HOST_STATUS 0x00000000 |
166 | #define IF_CS_H_STATUS_RX_OVER 0x0002 | ||
167 | #define IF_CS_H_STATUS_DNLD_OVER 0x0004 | ||
168 | 172 | ||
169 | #define IF_CS_H_INT_CAUSE 0x00000002 | 173 | #define IF_CS_HOST_INT_CAUSE 0x00000002 |
170 | #define IF_CS_H_IC_TX_OVER 0x0001 | ||
171 | #define IF_CS_H_IC_RX_OVER 0x0002 | ||
172 | #define IF_CS_H_IC_DNLD_OVER 0x0004 | ||
173 | #define IF_CS_H_IC_POWER_DOWN 0x0008 | ||
174 | #define IF_CS_H_IC_HOST_EVENT 0x0010 | ||
175 | #define IF_CS_H_IC_MASK 0x001f | ||
176 | 174 | ||
177 | #define IF_CS_H_INT_MASK 0x00000004 | 175 | #define IF_CS_HOST_INT_MASK 0x00000004 |
178 | #define IF_CS_H_IM_MASK 0x001f | ||
179 | 176 | ||
180 | #define IF_CS_H_WRITE_LEN 0x00000014 | 177 | #define IF_CS_HOST_WRITE 0x00000016 |
178 | #define IF_CS_HOST_WRITE_LEN 0x00000014 | ||
181 | 179 | ||
182 | #define IF_CS_H_WRITE 0x00000016 | 180 | #define IF_CS_HOST_CMD 0x0000001A |
181 | #define IF_CS_HOST_CMD_LEN 0x00000018 | ||
183 | 182 | ||
184 | #define IF_CS_H_CMD_LEN 0x00000018 | 183 | #define IF_CS_READ 0x00000010 |
184 | #define IF_CS_READ_LEN 0x00000024 | ||
185 | 185 | ||
186 | #define IF_CS_H_CMD 0x0000001A | 186 | #define IF_CS_CARD_CMD 0x00000012 |
187 | #define IF_CS_CARD_CMD_LEN 0x00000030 | ||
187 | 188 | ||
188 | #define IF_CS_C_READ_LEN 0x00000024 | 189 | #define IF_CS_CARD_STATUS 0x00000020 |
190 | #define IF_CS_CARD_STATUS_MASK 0x7f00 | ||
189 | 191 | ||
190 | #define IF_CS_H_READ 0x00000010 | 192 | #define IF_CS_CARD_INT_CAUSE 0x00000022 |
191 | 193 | ||
192 | /* Card control registers and their bit definitions */ | 194 | #define IF_CS_CARD_SQ_READ_LOW 0x00000028 |
193 | 195 | #define IF_CS_CARD_SQ_HELPER_OK 0x10 | |
194 | #define IF_CS_C_STATUS 0x00000020 | ||
195 | #define IF_CS_C_S_TX_DNLD_RDY 0x0001 | ||
196 | #define IF_CS_C_S_RX_UPLD_RDY 0x0002 | ||
197 | #define IF_CS_C_S_CMD_DNLD_RDY 0x0004 | ||
198 | #define IF_CS_C_S_CMD_UPLD_RDY 0x0008 | ||
199 | #define IF_CS_C_S_CARDEVENT 0x0010 | ||
200 | #define IF_CS_C_S_MASK 0x001f | ||
201 | #define IF_CS_C_S_STATUS_MASK 0x7f00 | ||
202 | |||
203 | #define IF_CS_C_INT_CAUSE 0x00000022 | ||
204 | #define IF_CS_C_IC_MASK 0x001f | ||
205 | |||
206 | #define IF_CS_C_SQ_READ_LOW 0x00000028 | ||
207 | #define IF_CS_C_SQ_HELPER_OK 0x10 | ||
208 | |||
209 | #define IF_CS_C_CMD_LEN 0x00000030 | ||
210 | |||
211 | #define IF_CS_C_CMD 0x00000012 | ||
212 | 196 | ||
213 | #define IF_CS_SCRATCH 0x0000003F | 197 | #define IF_CS_SCRATCH 0x0000003F |
214 | 198 | ||
215 | 199 | ||
216 | 200 | ||
217 | /********************************************************************/ | 201 | /********************************************************************/ |
218 | /* I/O */ | 202 | /* I/O and interrupt handling */ |
219 | /********************************************************************/ | 203 | /********************************************************************/ |
220 | 204 | ||
205 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
206 | { | ||
207 | lbs_deb_enter(LBS_DEB_CS); | ||
208 | if_cs_write16(card, IF_CS_HOST_INT_MASK, 0); | ||
209 | } | ||
210 | |||
211 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
212 | { | ||
213 | lbs_deb_enter(LBS_DEB_CS); | ||
214 | if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK); | ||
215 | } | ||
216 | |||
221 | /* | 217 | /* |
222 | * Called from if_cs_host_to_card to send a command to the hardware | 218 | * Called from if_cs_host_to_card to send a command to the hardware |
223 | */ | 219 | */ |
@@ -228,11 +224,12 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) | |||
228 | int loops = 0; | 224 | int loops = 0; |
229 | 225 | ||
230 | lbs_deb_enter(LBS_DEB_CS); | 226 | lbs_deb_enter(LBS_DEB_CS); |
227 | if_cs_disable_ints(card); | ||
231 | 228 | ||
232 | /* Is hardware ready? */ | 229 | /* Is hardware ready? */ |
233 | while (1) { | 230 | while (1) { |
234 | u16 val = if_cs_read16(card, IF_CS_C_STATUS); | 231 | u16 val = if_cs_read16(card, IF_CS_CARD_STATUS); |
235 | if (val & IF_CS_C_S_CMD_DNLD_RDY) | 232 | if (val & IF_CS_BIT_COMMAND) |
236 | break; | 233 | break; |
237 | if (++loops > 100) { | 234 | if (++loops > 100) { |
238 | lbs_pr_err("card not ready for commands\n"); | 235 | lbs_pr_err("card not ready for commands\n"); |
@@ -241,51 +238,56 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) | |||
241 | mdelay(1); | 238 | mdelay(1); |
242 | } | 239 | } |
243 | 240 | ||
244 | if_cs_write16(card, IF_CS_H_CMD_LEN, nb); | 241 | if_cs_write16(card, IF_CS_HOST_CMD_LEN, nb); |
245 | 242 | ||
246 | if_cs_write16_rep(card, IF_CS_H_CMD, buf, nb / 2); | 243 | if_cs_write16_rep(card, IF_CS_HOST_CMD, buf, nb / 2); |
247 | /* Are we supposed to transfer an odd amount of bytes? */ | 244 | /* Are we supposed to transfer an odd amount of bytes? */ |
248 | if (nb & 1) | 245 | if (nb & 1) |
249 | if_cs_write8(card, IF_CS_H_CMD, buf[nb-1]); | 246 | if_cs_write8(card, IF_CS_HOST_CMD, buf[nb-1]); |
250 | 247 | ||
251 | /* "Assert the download over interrupt command in the Host | 248 | /* "Assert the download over interrupt command in the Host |
252 | * status register" */ | 249 | * status register" */ |
253 | if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER); | 250 | if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); |
254 | 251 | ||
255 | /* "Assert the download over interrupt command in the Card | 252 | /* "Assert the download over interrupt command in the Card |
256 | * interrupt case register" */ | 253 | * interrupt case register" */ |
257 | if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER); | 254 | if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); |
258 | ret = 0; | 255 | ret = 0; |
259 | 256 | ||
260 | done: | 257 | done: |
258 | if_cs_enable_ints(card); | ||
261 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 259 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
262 | return ret; | 260 | return ret; |
263 | } | 261 | } |
264 | 262 | ||
265 | |||
266 | /* | 263 | /* |
267 | * Called from if_cs_host_to_card to send a data to the hardware | 264 | * Called from if_cs_host_to_card to send a data to the hardware |
268 | */ | 265 | */ |
269 | static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) | 266 | static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) |
270 | { | 267 | { |
271 | struct if_cs_card *card = (struct if_cs_card *)priv->card; | 268 | struct if_cs_card *card = (struct if_cs_card *)priv->card; |
269 | u16 status; | ||
272 | 270 | ||
273 | lbs_deb_enter(LBS_DEB_CS); | 271 | lbs_deb_enter(LBS_DEB_CS); |
272 | if_cs_disable_ints(card); | ||
273 | |||
274 | status = if_cs_read16(card, IF_CS_CARD_STATUS); | ||
275 | BUG_ON((status & IF_CS_BIT_TX) == 0); | ||
274 | 276 | ||
275 | if_cs_write16(card, IF_CS_H_WRITE_LEN, nb); | 277 | if_cs_write16(card, IF_CS_HOST_WRITE_LEN, nb); |
276 | 278 | ||
277 | /* write even number of bytes, then odd byte if necessary */ | 279 | /* write even number of bytes, then odd byte if necessary */ |
278 | if_cs_write16_rep(card, IF_CS_H_WRITE, buf, nb / 2); | 280 | if_cs_write16_rep(card, IF_CS_HOST_WRITE, buf, nb / 2); |
279 | if (nb & 1) | 281 | if (nb & 1) |
280 | if_cs_write8(card, IF_CS_H_WRITE, buf[nb-1]); | 282 | if_cs_write8(card, IF_CS_HOST_WRITE, buf[nb-1]); |
281 | 283 | ||
282 | if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_TX_OVER); | 284 | if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX); |
283 | if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_STATUS_TX_OVER); | 285 | if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX); |
286 | if_cs_enable_ints(card); | ||
284 | 287 | ||
285 | lbs_deb_leave(LBS_DEB_CS); | 288 | lbs_deb_leave(LBS_DEB_CS); |
286 | } | 289 | } |
287 | 290 | ||
288 | |||
289 | /* | 291 | /* |
290 | * Get the command result out of the card. | 292 | * Get the command result out of the card. |
291 | */ | 293 | */ |
@@ -293,27 +295,28 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | |||
293 | { | 295 | { |
294 | unsigned long flags; | 296 | unsigned long flags; |
295 | int ret = -1; | 297 | int ret = -1; |
296 | u16 val; | 298 | u16 status; |
297 | 299 | ||
298 | lbs_deb_enter(LBS_DEB_CS); | 300 | lbs_deb_enter(LBS_DEB_CS); |
299 | 301 | ||
300 | /* is hardware ready? */ | 302 | /* is hardware ready? */ |
301 | val = if_cs_read16(priv->card, IF_CS_C_STATUS); | 303 | status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); |
302 | if ((val & IF_CS_C_S_CMD_UPLD_RDY) == 0) { | 304 | if ((status & IF_CS_BIT_RESP) == 0) { |
303 | lbs_pr_err("card not ready for CMD\n"); | 305 | lbs_pr_err("no cmd response in card\n"); |
306 | *len = 0; | ||
304 | goto out; | 307 | goto out; |
305 | } | 308 | } |
306 | 309 | ||
307 | *len = if_cs_read16(priv->card, IF_CS_C_CMD_LEN); | 310 | *len = if_cs_read16(priv->card, IF_CS_CARD_CMD_LEN); |
308 | if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { | 311 | if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { |
309 | lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); | 312 | lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); |
310 | goto out; | 313 | goto out; |
311 | } | 314 | } |
312 | 315 | ||
313 | /* read even number of bytes, then odd byte if necessary */ | 316 | /* read even number of bytes, then odd byte if necessary */ |
314 | if_cs_read16_rep(priv->card, IF_CS_C_CMD, data, *len/sizeof(u16)); | 317 | if_cs_read16_rep(priv->card, IF_CS_CARD_CMD, data, *len/sizeof(u16)); |
315 | if (*len & 1) | 318 | if (*len & 1) |
316 | data[*len-1] = if_cs_read8(priv->card, IF_CS_C_CMD); | 319 | data[*len-1] = if_cs_read8(priv->card, IF_CS_CARD_CMD); |
317 | 320 | ||
318 | /* This is a workaround for a firmware that reports too much | 321 | /* This is a workaround for a firmware that reports too much |
319 | * bytes */ | 322 | * bytes */ |
@@ -330,7 +333,6 @@ out: | |||
330 | return ret; | 333 | return ret; |
331 | } | 334 | } |
332 | 335 | ||
333 | |||
334 | static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | 336 | static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) |
335 | { | 337 | { |
336 | struct sk_buff *skb = NULL; | 338 | struct sk_buff *skb = NULL; |
@@ -339,7 +341,7 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | |||
339 | 341 | ||
340 | lbs_deb_enter(LBS_DEB_CS); | 342 | lbs_deb_enter(LBS_DEB_CS); |
341 | 343 | ||
342 | len = if_cs_read16(priv->card, IF_CS_C_READ_LEN); | 344 | len = if_cs_read16(priv->card, IF_CS_READ_LEN); |
343 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | 345 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { |
344 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); | 346 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); |
345 | priv->stats.rx_dropped++; | 347 | priv->stats.rx_dropped++; |
@@ -354,38 +356,19 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | |||
354 | data = skb->data; | 356 | data = skb->data; |
355 | 357 | ||
356 | /* read even number of bytes, then odd byte if necessary */ | 358 | /* read even number of bytes, then odd byte if necessary */ |
357 | if_cs_read16_rep(priv->card, IF_CS_H_READ, data, len/sizeof(u16)); | 359 | if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16)); |
358 | if (len & 1) | 360 | if (len & 1) |
359 | data[len-1] = if_cs_read8(priv->card, IF_CS_H_READ); | 361 | data[len-1] = if_cs_read8(priv->card, IF_CS_READ); |
360 | 362 | ||
361 | dat_err: | 363 | dat_err: |
362 | if_cs_write16(priv->card, IF_CS_H_STATUS, IF_CS_H_STATUS_RX_OVER); | 364 | if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX); |
363 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_RX_OVER); | 365 | if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX); |
364 | 366 | ||
365 | out: | 367 | out: |
366 | lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb); | 368 | lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb); |
367 | return skb; | 369 | return skb; |
368 | } | 370 | } |
369 | 371 | ||
370 | |||
371 | |||
372 | /********************************************************************/ | ||
373 | /* Interrupts */ | ||
374 | /********************************************************************/ | ||
375 | |||
376 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
377 | { | ||
378 | lbs_deb_enter(LBS_DEB_CS); | ||
379 | if_cs_write16(card, IF_CS_H_INT_MASK, 0); | ||
380 | } | ||
381 | |||
382 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
383 | { | ||
384 | lbs_deb_enter(LBS_DEB_CS); | ||
385 | if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); | ||
386 | } | ||
387 | |||
388 | |||
389 | static irqreturn_t if_cs_interrupt(int irq, void *data) | 372 | static irqreturn_t if_cs_interrupt(int irq, void *data) |
390 | { | 373 | { |
391 | struct if_cs_card *card = data; | 374 | struct if_cs_card *card = data; |
@@ -394,10 +377,8 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
394 | 377 | ||
395 | lbs_deb_enter(LBS_DEB_CS); | 378 | lbs_deb_enter(LBS_DEB_CS); |
396 | 379 | ||
397 | cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); | 380 | /* Ask card interrupt cause register if there is something for us */ |
398 | if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK); | 381 | cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE); |
399 | |||
400 | lbs_deb_cs("cause 0x%04x\n", cause); | ||
401 | if (cause == 0) { | 382 | if (cause == 0) { |
402 | /* Not for us */ | 383 | /* Not for us */ |
403 | return IRQ_NONE; | 384 | return IRQ_NONE; |
@@ -409,11 +390,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
409 | return IRQ_HANDLED; | 390 | return IRQ_HANDLED; |
410 | } | 391 | } |
411 | 392 | ||
412 | /* TODO: I'm not sure what the best ordering is */ | 393 | /* Clear interrupt cause */ |
413 | 394 | if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK); | |
414 | cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; | 395 | lbs_deb_cs("cause 0x%04x\n", cause); |
415 | 396 | ||
416 | if (cause & IF_CS_C_S_RX_UPLD_RDY) { | 397 | if (cause & IF_CS_BIT_RX) { |
417 | struct sk_buff *skb; | 398 | struct sk_buff *skb; |
418 | lbs_deb_cs("rx packet\n"); | 399 | lbs_deb_cs("rx packet\n"); |
419 | skb = if_cs_receive_data(priv); | 400 | skb = if_cs_receive_data(priv); |
@@ -421,16 +402,16 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
421 | lbs_process_rxed_packet(priv, skb); | 402 | lbs_process_rxed_packet(priv, skb); |
422 | } | 403 | } |
423 | 404 | ||
424 | if (cause & IF_CS_H_IC_TX_OVER) { | 405 | if (cause & IF_CS_BIT_TX) { |
425 | lbs_deb_cs("tx over\n"); | 406 | lbs_deb_cs("tx done\n"); |
426 | lbs_host_to_card_done(priv); | 407 | lbs_host_to_card_done(priv); |
427 | } | 408 | } |
428 | 409 | ||
429 | if (cause & IF_CS_C_S_CMD_UPLD_RDY) { | 410 | if (cause & IF_CS_BIT_RESP) { |
430 | unsigned long flags; | 411 | unsigned long flags; |
431 | u8 i; | 412 | u8 i; |
432 | 413 | ||
433 | lbs_deb_cs("cmd upload ready\n"); | 414 | lbs_deb_cs("cmd resp\n"); |
434 | spin_lock_irqsave(&priv->driver_lock, flags); | 415 | spin_lock_irqsave(&priv->driver_lock, flags); |
435 | i = (priv->resp_idx == 0) ? 1 : 0; | 416 | i = (priv->resp_idx == 0) ? 1 : 0; |
436 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 417 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
@@ -444,15 +425,16 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
444 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 425 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
445 | } | 426 | } |
446 | 427 | ||
447 | if (cause & IF_CS_H_IC_HOST_EVENT) { | 428 | if (cause & IF_CS_BIT_EVENT) { |
448 | u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS) | 429 | u16 event = if_cs_read16(priv->card, IF_CS_CARD_STATUS) |
449 | & IF_CS_C_S_STATUS_MASK; | 430 | & IF_CS_CARD_STATUS_MASK; |
450 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, | 431 | if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, |
451 | IF_CS_H_IC_HOST_EVENT); | 432 | IF_CS_BIT_EVENT); |
452 | lbs_deb_cs("eventcause 0x%04x\n", event); | 433 | lbs_deb_cs("host event 0x%04x\n", event); |
453 | lbs_queue_event(priv, event >> 8 & 0xff); | 434 | lbs_queue_event(priv, event >> 8 & 0xff); |
454 | } | 435 | } |
455 | 436 | ||
437 | lbs_deb_leave(LBS_DEB_CS); | ||
456 | return IRQ_HANDLED; | 438 | return IRQ_HANDLED; |
457 | } | 439 | } |
458 | 440 | ||
@@ -514,26 +496,26 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
514 | 496 | ||
515 | /* "write the number of bytes to be sent to the I/O Command | 497 | /* "write the number of bytes to be sent to the I/O Command |
516 | * write length register" */ | 498 | * write length register" */ |
517 | if_cs_write16(card, IF_CS_H_CMD_LEN, count); | 499 | if_cs_write16(card, IF_CS_HOST_CMD_LEN, count); |
518 | 500 | ||
519 | /* "write this to I/O Command port register as 16 bit writes */ | 501 | /* "write this to I/O Command port register as 16 bit writes */ |
520 | if (count) | 502 | if (count) |
521 | if_cs_write16_rep(card, IF_CS_H_CMD, | 503 | if_cs_write16_rep(card, IF_CS_HOST_CMD, |
522 | &fw->data[sent], | 504 | &fw->data[sent], |
523 | count >> 1); | 505 | count >> 1); |
524 | 506 | ||
525 | /* "Assert the download over interrupt command in the Host | 507 | /* "Assert the download over interrupt command in the Host |
526 | * status register" */ | 508 | * status register" */ |
527 | if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER); | 509 | if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); |
528 | 510 | ||
529 | /* "Assert the download over interrupt command in the Card | 511 | /* "Assert the download over interrupt command in the Card |
530 | * interrupt case register" */ | 512 | * interrupt case register" */ |
531 | if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER); | 513 | if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); |
532 | 514 | ||
533 | /* "The host polls the Card Status register ... for 50 ms before | 515 | /* "The host polls the Card Status register ... for 50 ms before |
534 | declaring a failure */ | 516 | declaring a failure */ |
535 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS, | 517 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, |
536 | IF_CS_C_S_CMD_DNLD_RDY); | 518 | IF_CS_BIT_COMMAND); |
537 | if (ret < 0) { | 519 | if (ret < 0) { |
538 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 520 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", |
539 | sent, ret); | 521 | sent, ret); |
@@ -575,14 +557,15 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
575 | } | 557 | } |
576 | lbs_deb_cs("fw size %td\n", fw->size); | 558 | lbs_deb_cs("fw size %td\n", fw->size); |
577 | 559 | ||
578 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); | 560 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_SQ_READ_LOW, |
561 | IF_CS_CARD_SQ_HELPER_OK); | ||
579 | if (ret < 0) { | 562 | if (ret < 0) { |
580 | lbs_pr_err("helper firmware doesn't answer\n"); | 563 | lbs_pr_err("helper firmware doesn't answer\n"); |
581 | goto err_release; | 564 | goto err_release; |
582 | } | 565 | } |
583 | 566 | ||
584 | for (sent = 0; sent < fw->size; sent += len) { | 567 | for (sent = 0; sent < fw->size; sent += len) { |
585 | len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); | 568 | len = if_cs_read16(card, IF_CS_CARD_SQ_READ_LOW); |
586 | if (len & 1) { | 569 | if (len & 1) { |
587 | retry++; | 570 | retry++; |
588 | lbs_pr_info("odd, need to retry this firmware block\n"); | 571 | lbs_pr_info("odd, need to retry this firmware block\n"); |
@@ -600,16 +583,16 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
600 | } | 583 | } |
601 | 584 | ||
602 | 585 | ||
603 | if_cs_write16(card, IF_CS_H_CMD_LEN, len); | 586 | if_cs_write16(card, IF_CS_HOST_CMD_LEN, len); |
604 | 587 | ||
605 | if_cs_write16_rep(card, IF_CS_H_CMD, | 588 | if_cs_write16_rep(card, IF_CS_HOST_CMD, |
606 | &fw->data[sent], | 589 | &fw->data[sent], |
607 | (len+1) >> 1); | 590 | (len+1) >> 1); |
608 | if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER); | 591 | if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); |
609 | if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER); | 592 | if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); |
610 | 593 | ||
611 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS, | 594 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, |
612 | IF_CS_C_S_CMD_DNLD_RDY); | 595 | IF_CS_BIT_COMMAND); |
613 | if (ret < 0) { | 596 | if (ret < 0) { |
614 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 597 | lbs_pr_err("can't download firmware at 0x%x\n", sent); |
615 | goto err_release; | 598 | goto err_release; |
@@ -837,7 +820,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
837 | 820 | ||
838 | /* Clear any interrupt cause that happend while sending | 821 | /* Clear any interrupt cause that happend while sending |
839 | * firmware/initializing card */ | 822 | * firmware/initializing card */ |
840 | if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK); | 823 | if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); |
841 | if_cs_enable_ints(card); | 824 | if_cs_enable_ints(card); |
842 | 825 | ||
843 | /* And finally bring the card up */ | 826 | /* And finally bring the card up */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 8032df72aaab..24783103a7dd 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -7,6 +7,10 @@ | |||
7 | #include <linux/netdevice.h> | 7 | #include <linux/netdevice.h> |
8 | #include <linux/usb.h> | 8 | #include <linux/usb.h> |
9 | 9 | ||
10 | #ifdef CONFIG_OLPC | ||
11 | #include <asm/olpc.h> | ||
12 | #endif | ||
13 | |||
10 | #define DRV_NAME "usb8xxx" | 14 | #define DRV_NAME "usb8xxx" |
11 | 15 | ||
12 | #include "host.h" | 16 | #include "host.h" |
@@ -146,6 +150,14 @@ static void if_usb_fw_timeo(unsigned long priv) | |||
146 | wake_up(&cardp->fw_wq); | 150 | wake_up(&cardp->fw_wq); |
147 | } | 151 | } |
148 | 152 | ||
153 | #ifdef CONFIG_OLPC | ||
154 | static void if_usb_reset_olpc_card(struct lbs_private *priv) | ||
155 | { | ||
156 | printk(KERN_CRIT "Resetting OLPC wireless via EC...\n"); | ||
157 | olpc_ec_cmd(0x25, NULL, 0, NULL, 0); | ||
158 | } | ||
159 | #endif | ||
160 | |||
149 | /** | 161 | /** |
150 | * @brief sets the configuration values | 162 | * @brief sets the configuration values |
151 | * @param ifnum interface number | 163 | * @param ifnum interface number |
@@ -231,6 +243,11 @@ static int if_usb_probe(struct usb_interface *intf, | |||
231 | cardp->priv->fw_ready = 1; | 243 | cardp->priv->fw_ready = 1; |
232 | 244 | ||
233 | priv->hw_host_to_card = if_usb_host_to_card; | 245 | priv->hw_host_to_card = if_usb_host_to_card; |
246 | #ifdef CONFIG_OLPC | ||
247 | if (machine_is_olpc()) | ||
248 | priv->reset_card = if_usb_reset_olpc_card; | ||
249 | #endif | ||
250 | |||
234 | cardp->boot2_version = udev->descriptor.bcdDevice; | 251 | cardp->boot2_version = udev->descriptor.bcdDevice; |
235 | 252 | ||
236 | if_usb_submit_rx_urb(cardp); | 253 | if_usb_submit_rx_urb(cardp); |
@@ -364,6 +381,11 @@ static int if_usb_reset_device(struct if_usb_card *cardp) | |||
364 | ret = usb_reset_device(cardp->udev); | 381 | ret = usb_reset_device(cardp->udev); |
365 | msleep(100); | 382 | msleep(100); |
366 | 383 | ||
384 | #ifdef CONFIG_OLPC | ||
385 | if (ret && machine_is_olpc()) | ||
386 | if_usb_reset_olpc_card(NULL); | ||
387 | #endif | ||
388 | |||
367 | lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); | 389 | lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); |
368 | 390 | ||
369 | return ret; | 391 | return ret; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 02e4fb639428..b7ab3590b586 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
14 | #include <linux/stddef.h> | ||
14 | 15 | ||
15 | #include <net/iw_handler.h> | 16 | #include <net/iw_handler.h> |
16 | #include <net/ieee80211.h> | 17 | #include <net/ieee80211.h> |
@@ -343,14 +344,15 @@ static ssize_t lbs_mesh_set(struct device *dev, | |||
343 | { | 344 | { |
344 | struct lbs_private *priv = to_net_dev(dev)->priv; | 345 | struct lbs_private *priv = to_net_dev(dev)->priv; |
345 | int enable; | 346 | int enable; |
346 | int ret; | 347 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; |
347 | 348 | ||
348 | sscanf(buf, "%x", &enable); | 349 | sscanf(buf, "%x", &enable); |
349 | enable = !!enable; | 350 | enable = !!enable; |
350 | if (enable == !!priv->mesh_dev) | 351 | if (enable == !!priv->mesh_dev) |
351 | return count; | 352 | return count; |
352 | 353 | if (enable) | |
353 | ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel); | 354 | action = CMD_ACT_MESH_CONFIG_START; |
355 | ret = lbs_mesh_config(priv, action, priv->curbssparams.channel); | ||
354 | if (ret) | 356 | if (ret) |
355 | return ret; | 357 | return ret; |
356 | 358 | ||
@@ -446,6 +448,8 @@ static int lbs_mesh_stop(struct net_device *dev) | |||
446 | 448 | ||
447 | spin_unlock_irq(&priv->driver_lock); | 449 | spin_unlock_irq(&priv->driver_lock); |
448 | 450 | ||
451 | schedule_work(&priv->mcast_work); | ||
452 | |||
449 | lbs_deb_leave(LBS_DEB_MESH); | 453 | lbs_deb_leave(LBS_DEB_MESH); |
450 | return 0; | 454 | return 0; |
451 | } | 455 | } |
@@ -467,6 +471,8 @@ static int lbs_eth_stop(struct net_device *dev) | |||
467 | netif_stop_queue(dev); | 471 | netif_stop_queue(dev); |
468 | spin_unlock_irq(&priv->driver_lock); | 472 | spin_unlock_irq(&priv->driver_lock); |
469 | 473 | ||
474 | schedule_work(&priv->mcast_work); | ||
475 | |||
470 | lbs_deb_leave(LBS_DEB_NET); | 476 | lbs_deb_leave(LBS_DEB_NET); |
471 | return 0; | 477 | return 0; |
472 | } | 478 | } |
@@ -563,89 +569,116 @@ done: | |||
563 | return ret; | 569 | return ret; |
564 | } | 570 | } |
565 | 571 | ||
566 | static int lbs_copy_multicast_address(struct lbs_private *priv, | 572 | |
567 | struct net_device *dev) | 573 | static inline int mac_in_list(unsigned char *list, int list_len, |
574 | unsigned char *mac) | ||
568 | { | 575 | { |
569 | int i = 0; | 576 | while (list_len) { |
570 | struct dev_mc_list *mcptr = dev->mc_list; | 577 | if (!memcmp(list, mac, ETH_ALEN)) |
578 | return 1; | ||
579 | list += ETH_ALEN; | ||
580 | list_len--; | ||
581 | } | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | |||
586 | static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, | ||
587 | struct net_device *dev, int nr_addrs) | ||
588 | { | ||
589 | int i = nr_addrs; | ||
590 | struct dev_mc_list *mc_list; | ||
591 | DECLARE_MAC_BUF(mac); | ||
592 | |||
593 | if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) | ||
594 | return nr_addrs; | ||
595 | |||
596 | netif_tx_lock_bh(dev); | ||
597 | for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { | ||
598 | if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { | ||
599 | lbs_deb_net("mcast address %s:%s skipped\n", dev->name, | ||
600 | print_mac(mac, mc_list->dmi_addr)); | ||
601 | continue; | ||
602 | } | ||
571 | 603 | ||
572 | for (i = 0; i < dev->mc_count; i++) { | 604 | if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) |
573 | memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN); | 605 | break; |
574 | mcptr = mcptr->next; | 606 | memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); |
607 | lbs_deb_net("mcast address %s:%s added to filter\n", dev->name, | ||
608 | print_mac(mac, mc_list->dmi_addr)); | ||
609 | i++; | ||
575 | } | 610 | } |
611 | netif_tx_unlock_bh(dev); | ||
612 | if (mc_list) | ||
613 | return -EOVERFLOW; | ||
614 | |||
576 | return i; | 615 | return i; |
577 | } | 616 | } |
578 | 617 | ||
579 | static void lbs_set_multicast_list(struct net_device *dev) | 618 | static void lbs_set_mcast_worker(struct work_struct *work) |
580 | { | 619 | { |
581 | struct lbs_private *priv = dev->priv; | 620 | struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); |
582 | int old_mac_control; | 621 | struct cmd_ds_mac_multicast_adr mcast_cmd; |
583 | DECLARE_MAC_BUF(mac); | 622 | int dev_flags; |
623 | int nr_addrs; | ||
624 | int old_mac_control = priv->mac_control; | ||
584 | 625 | ||
585 | lbs_deb_enter(LBS_DEB_NET); | 626 | lbs_deb_enter(LBS_DEB_NET); |
586 | 627 | ||
587 | old_mac_control = priv->mac_control; | 628 | dev_flags = priv->dev->flags; |
588 | 629 | if (priv->mesh_dev) | |
589 | if (dev->flags & IFF_PROMISC) { | 630 | dev_flags |= priv->mesh_dev->flags; |
590 | lbs_deb_net("enable promiscuous mode\n"); | 631 | |
591 | priv->mac_control |= | 632 | if (dev_flags & IFF_PROMISC) { |
592 | CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 633 | priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
593 | priv->mac_control &= | 634 | priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | |
594 | ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | | 635 | CMD_ACT_MAC_MULTICAST_ENABLE); |
595 | CMD_ACT_MAC_MULTICAST_ENABLE); | 636 | goto out_set_mac_control; |
596 | } else { | 637 | } else if (dev_flags & IFF_ALLMULTI) { |
597 | /* Multicast */ | 638 | do_allmulti: |
598 | priv->mac_control &= | 639 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
599 | ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 640 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | |
600 | 641 | CMD_ACT_MAC_MULTICAST_ENABLE); | |
601 | if (dev->flags & IFF_ALLMULTI || dev->mc_count > | 642 | goto out_set_mac_control; |
602 | MRVDRV_MAX_MULTICAST_LIST_SIZE) { | ||
603 | lbs_deb_net( "enabling all multicast\n"); | ||
604 | priv->mac_control |= | ||
605 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | ||
606 | priv->mac_control &= | ||
607 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
608 | } else { | ||
609 | priv->mac_control &= | ||
610 | ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | ||
611 | |||
612 | if (!dev->mc_count) { | ||
613 | lbs_deb_net("no multicast addresses, " | ||
614 | "disabling multicast\n"); | ||
615 | priv->mac_control &= | ||
616 | ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
617 | } else { | ||
618 | int i; | ||
619 | |||
620 | priv->mac_control |= | ||
621 | CMD_ACT_MAC_MULTICAST_ENABLE; | ||
622 | |||
623 | priv->nr_of_multicastmacaddr = | ||
624 | lbs_copy_multicast_address(priv, dev); | ||
625 | |||
626 | lbs_deb_net("multicast addresses: %d\n", | ||
627 | dev->mc_count); | ||
628 | |||
629 | for (i = 0; i < dev->mc_count; i++) { | ||
630 | lbs_deb_net("Multicast address %d: %s\n", | ||
631 | i, print_mac(mac, | ||
632 | priv->multicastlist[i])); | ||
633 | } | ||
634 | /* send multicast addresses to firmware */ | ||
635 | lbs_prepare_and_send_command(priv, | ||
636 | CMD_MAC_MULTICAST_ADR, | ||
637 | CMD_ACT_SET, 0, 0, | ||
638 | NULL); | ||
639 | } | ||
640 | } | ||
641 | } | 643 | } |
642 | 644 | ||
645 | /* Once for priv->dev, again for priv->mesh_dev if it exists */ | ||
646 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->dev, 0); | ||
647 | if (nr_addrs >= 0 && priv->mesh_dev) | ||
648 | nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->mesh_dev, nr_addrs); | ||
649 | if (nr_addrs < 0) | ||
650 | goto do_allmulti; | ||
651 | |||
652 | if (nr_addrs) { | ||
653 | int size = offsetof(struct cmd_ds_mac_multicast_adr, | ||
654 | maclist[6*nr_addrs]); | ||
655 | |||
656 | mcast_cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
657 | mcast_cmd.hdr.size = cpu_to_le16(size); | ||
658 | mcast_cmd.nr_of_adrs = cpu_to_le16(nr_addrs); | ||
659 | |||
660 | lbs_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &mcast_cmd.hdr, size); | ||
661 | |||
662 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; | ||
663 | } else | ||
664 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; | ||
665 | |||
666 | priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | | ||
667 | CMD_ACT_MAC_ALL_MULTICAST_ENABLE); | ||
668 | out_set_mac_control: | ||
643 | if (priv->mac_control != old_mac_control) | 669 | if (priv->mac_control != old_mac_control) |
644 | lbs_set_mac_control(priv); | 670 | lbs_set_mac_control(priv); |
645 | 671 | ||
646 | lbs_deb_leave(LBS_DEB_NET); | 672 | lbs_deb_leave(LBS_DEB_NET); |
647 | } | 673 | } |
648 | 674 | ||
675 | static void lbs_set_multicast_list(struct net_device *dev) | ||
676 | { | ||
677 | struct lbs_private *priv = dev->priv; | ||
678 | |||
679 | schedule_work(&priv->mcast_work); | ||
680 | } | ||
681 | |||
649 | /** | 682 | /** |
650 | * @brief This function handles the major jobs in the LBS driver. | 683 | * @brief This function handles the major jobs in the LBS driver. |
651 | * It handles all events generated by firmware, RX data received | 684 | * It handles all events generated by firmware, RX data received |
@@ -689,14 +722,14 @@ static int lbs_thread(void *data) | |||
689 | shouldsleep = 1; /* Something is en route to the device already */ | 722 | shouldsleep = 1; /* Something is en route to the device already */ |
690 | else if (priv->tx_pending_len > 0) | 723 | else if (priv->tx_pending_len > 0) |
691 | shouldsleep = 0; /* We've a packet to send */ | 724 | shouldsleep = 0; /* We've a packet to send */ |
725 | else if (priv->resp_len[priv->resp_idx]) | ||
726 | shouldsleep = 0; /* We have a command response */ | ||
692 | else if (priv->cur_cmd) | 727 | else if (priv->cur_cmd) |
693 | shouldsleep = 1; /* Can't send a command; one already running */ | 728 | shouldsleep = 1; /* Can't send a command; one already running */ |
694 | else if (!list_empty(&priv->cmdpendingq)) | 729 | else if (!list_empty(&priv->cmdpendingq)) |
695 | shouldsleep = 0; /* We have a command to send */ | 730 | shouldsleep = 0; /* We have a command to send */ |
696 | else if (__kfifo_len(priv->event_fifo)) | 731 | else if (__kfifo_len(priv->event_fifo)) |
697 | shouldsleep = 0; /* We have an event to process */ | 732 | shouldsleep = 0; /* We have an event to process */ |
698 | else if (priv->resp_len[priv->resp_idx]) | ||
699 | shouldsleep = 0; /* We have a command response */ | ||
700 | else | 733 | else |
701 | shouldsleep = 1; /* No command */ | 734 | shouldsleep = 1; /* No command */ |
702 | 735 | ||
@@ -749,16 +782,21 @@ static int lbs_thread(void *data) | |||
749 | if (priv->cmd_timed_out && priv->cur_cmd) { | 782 | if (priv->cmd_timed_out && priv->cur_cmd) { |
750 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 783 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
751 | 784 | ||
752 | if (++priv->nr_retries > 10) { | 785 | if (++priv->nr_retries > 3) { |
753 | lbs_pr_info("Excessive timeouts submitting command %x\n", | 786 | lbs_pr_info("Excessive timeouts submitting " |
754 | le16_to_cpu(cmdnode->cmdbuf->command)); | 787 | "command 0x%04x\n", |
788 | le16_to_cpu(cmdnode->cmdbuf->command)); | ||
755 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | 789 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); |
756 | priv->nr_retries = 0; | 790 | priv->nr_retries = 0; |
791 | if (priv->reset_card) | ||
792 | priv->reset_card(priv); | ||
757 | } else { | 793 | } else { |
758 | priv->cur_cmd = NULL; | 794 | priv->cur_cmd = NULL; |
759 | priv->dnld_sent = DNLD_RES_RECEIVED; | 795 | priv->dnld_sent = DNLD_RES_RECEIVED; |
760 | lbs_pr_info("requeueing command %x due to timeout (#%d)\n", | 796 | lbs_pr_info("requeueing command 0x%04x due " |
761 | le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries); | 797 | "to timeout (#%d)\n", |
798 | le16_to_cpu(cmdnode->cmdbuf->command), | ||
799 | priv->nr_retries); | ||
762 | 800 | ||
763 | /* Stick it back at the _top_ of the pending queue | 801 | /* Stick it back at the _top_ of the pending queue |
764 | for immediate resubmission */ | 802 | for immediate resubmission */ |
@@ -949,12 +987,11 @@ static void command_timer_fn(unsigned long data) | |||
949 | lbs_deb_enter(LBS_DEB_CMD); | 987 | lbs_deb_enter(LBS_DEB_CMD); |
950 | spin_lock_irqsave(&priv->driver_lock, flags); | 988 | spin_lock_irqsave(&priv->driver_lock, flags); |
951 | 989 | ||
952 | if (!priv->cur_cmd) { | 990 | if (!priv->cur_cmd) |
953 | lbs_pr_info("Command timer expired; no pending command\n"); | ||
954 | goto out; | 991 | goto out; |
955 | } | ||
956 | 992 | ||
957 | lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command)); | 993 | lbs_pr_info("command 0x%04x timed out\n", |
994 | le16_to_cpu(priv->cur_cmd->cmdbuf->command)); | ||
958 | 995 | ||
959 | priv->cmd_timed_out = 1; | 996 | priv->cmd_timed_out = 1; |
960 | wake_up_interruptible(&priv->waitq); | 997 | wake_up_interruptible(&priv->waitq); |
@@ -1008,7 +1045,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1008 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1045 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1009 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 1046 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1010 | priv->radioon = RADIO_ON; | 1047 | priv->radioon = RADIO_ON; |
1011 | priv->auto_rate = 1; | 1048 | priv->enablehwauto = 1; |
1012 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1049 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1013 | priv->psmode = LBS802_11POWERMODECAM; | 1050 | priv->psmode = LBS802_11POWERMODECAM; |
1014 | priv->psstate = PS_STATE_FULL_POWER; | 1051 | priv->psstate = PS_STATE_FULL_POWER; |
@@ -1123,6 +1160,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1123 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 1160 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
1124 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 1161 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
1125 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 1162 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1163 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | ||
1126 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | 1164 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); |
1127 | 1165 | ||
1128 | sprintf(priv->mesh_ssid, "mesh"); | 1166 | sprintf(priv->mesh_ssid, "mesh"); |
@@ -1159,6 +1197,7 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1159 | 1197 | ||
1160 | cancel_delayed_work_sync(&priv->scan_work); | 1198 | cancel_delayed_work_sync(&priv->scan_work); |
1161 | cancel_delayed_work_sync(&priv->assoc_work); | 1199 | cancel_delayed_work_sync(&priv->assoc_work); |
1200 | cancel_work_sync(&priv->mcast_work); | ||
1162 | destroy_workqueue(priv->work_thread); | 1201 | destroy_workqueue(priv->work_thread); |
1163 | 1202 | ||
1164 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | 1203 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { |
@@ -1224,9 +1263,11 @@ int lbs_start_card(struct lbs_private *priv) | |||
1224 | useful */ | 1263 | useful */ |
1225 | 1264 | ||
1226 | priv->mesh_tlv = 0x100 + 291; | 1265 | priv->mesh_tlv = 0x100 + 291; |
1227 | if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) { | 1266 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1267 | priv->curbssparams.channel)) { | ||
1228 | priv->mesh_tlv = 0x100 + 37; | 1268 | priv->mesh_tlv = 0x100 + 37; |
1229 | if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) | 1269 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1270 | priv->curbssparams.channel)) | ||
1230 | priv->mesh_tlv = 0; | 1271 | priv->mesh_tlv = 0; |
1231 | } | 1272 | } |
1232 | if (priv->mesh_tlv) { | 1273 | if (priv->mesh_tlv) { |
@@ -1266,8 +1307,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1266 | 1307 | ||
1267 | lbs_debugfs_remove_one(priv); | 1308 | lbs_debugfs_remove_one(priv); |
1268 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1309 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1269 | if (priv->mesh_tlv) | 1310 | if (priv->mesh_tlv) { |
1270 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); | 1311 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); |
1312 | } | ||
1271 | 1313 | ||
1272 | /* Flush pending command nodes */ | 1314 | /* Flush pending command nodes */ |
1273 | del_timer_sync(&priv->command_timer); | 1315 | del_timer_sync(&priv->command_timer); |
@@ -1323,6 +1365,8 @@ static int lbs_add_mesh(struct lbs_private *priv) | |||
1323 | #ifdef WIRELESS_EXT | 1365 | #ifdef WIRELESS_EXT |
1324 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; | 1366 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; |
1325 | #endif | 1367 | #endif |
1368 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1369 | mesh_dev->set_multicast_list = lbs_set_multicast_list; | ||
1326 | /* Register virtual mesh interface */ | 1370 | /* Register virtual mesh interface */ |
1327 | ret = register_netdev(mesh_dev); | 1371 | ret = register_netdev(mesh_dev); |
1328 | if (ret) { | 1372 | if (ret) { |
@@ -1334,6 +1378,8 @@ static int lbs_add_mesh(struct lbs_private *priv) | |||
1334 | if (ret) | 1378 | if (ret) |
1335 | goto err_unregister; | 1379 | goto err_unregister; |
1336 | 1380 | ||
1381 | lbs_persist_config_init(mesh_dev); | ||
1382 | |||
1337 | /* Everything successful */ | 1383 | /* Everything successful */ |
1338 | ret = 0; | 1384 | ret = 0; |
1339 | goto done; | 1385 | goto done; |
@@ -1360,8 +1406,9 @@ static void lbs_remove_mesh(struct lbs_private *priv) | |||
1360 | 1406 | ||
1361 | lbs_deb_enter(LBS_DEB_MESH); | 1407 | lbs_deb_enter(LBS_DEB_MESH); |
1362 | netif_stop_queue(mesh_dev); | 1408 | netif_stop_queue(mesh_dev); |
1363 | netif_carrier_off(priv->mesh_dev); | 1409 | netif_carrier_off(mesh_dev); |
1364 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | 1410 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); |
1411 | lbs_persist_config_remove(mesh_dev); | ||
1365 | unregister_netdev(mesh_dev); | 1412 | unregister_netdev(mesh_dev); |
1366 | priv->mesh_dev = NULL; | 1413 | priv->mesh_dev = NULL; |
1367 | free_netdev(mesh_dev); | 1414 | free_netdev(mesh_dev); |
@@ -1555,7 +1602,6 @@ static int lbs_add_rtap(struct lbs_private *priv) | |||
1555 | rtap_dev->stop = lbs_rtap_stop; | 1602 | rtap_dev->stop = lbs_rtap_stop; |
1556 | rtap_dev->get_stats = lbs_rtap_get_stats; | 1603 | rtap_dev->get_stats = lbs_rtap_get_stats; |
1557 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; | 1604 | rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; |
1558 | rtap_dev->set_multicast_list = lbs_set_multicast_list; | ||
1559 | rtap_dev->priv = priv; | 1605 | rtap_dev->priv = priv; |
1560 | SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); | 1606 | SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); |
1561 | 1607 | ||
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c new file mode 100644 index 000000000000..6d0ff8decaf7 --- /dev/null +++ b/drivers/net/wireless/libertas/persistcfg.c | |||
@@ -0,0 +1,453 @@ | |||
1 | #include <linux/moduleparam.h> | ||
2 | #include <linux/delay.h> | ||
3 | #include <linux/etherdevice.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/if_arp.h> | ||
6 | #include <linux/kthread.h> | ||
7 | #include <linux/kfifo.h> | ||
8 | |||
9 | #include "host.h" | ||
10 | #include "decl.h" | ||
11 | #include "dev.h" | ||
12 | #include "wext.h" | ||
13 | #include "debugfs.h" | ||
14 | #include "scan.h" | ||
15 | #include "assoc.h" | ||
16 | #include "cmd.h" | ||
17 | |||
18 | static int mesh_get_default_parameters(struct device *dev, | ||
19 | struct mrvl_mesh_defaults *defs) | ||
20 | { | ||
21 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
22 | struct cmd_ds_mesh_config cmd; | ||
23 | int ret; | ||
24 | |||
25 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
26 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET, | ||
27 | CMD_TYPE_MESH_GET_DEFAULTS); | ||
28 | |||
29 | if (ret) | ||
30 | return -EOPNOTSUPP; | ||
31 | |||
32 | memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults)); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * @brief Get function for sysfs attribute bootflag | ||
39 | */ | ||
40 | static ssize_t bootflag_get(struct device *dev, | ||
41 | struct device_attribute *attr, char *buf) | ||
42 | { | ||
43 | struct mrvl_mesh_defaults defs; | ||
44 | int ret; | ||
45 | |||
46 | ret = mesh_get_default_parameters(dev, &defs); | ||
47 | |||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | return snprintf(buf, 12, "0x%x\n", le32_to_cpu(defs.bootflag)); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * @brief Set function for sysfs attribute bootflag | ||
56 | */ | ||
57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, | ||
58 | const char *buf, size_t count) | ||
59 | { | ||
60 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
61 | struct cmd_ds_mesh_config cmd; | ||
62 | uint32_t datum; | ||
63 | int ret; | ||
64 | |||
65 | memset(&cmd, 0, sizeof(cmd)); | ||
66 | ret = sscanf(buf, "%x", &datum); | ||
67 | if (ret != 1) | ||
68 | return -EINVAL; | ||
69 | |||
70 | *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); | ||
71 | cmd.length = cpu_to_le16(sizeof(uint32_t)); | ||
72 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
73 | CMD_TYPE_MESH_SET_BOOTFLAG); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | return strlen(buf); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * @brief Get function for sysfs attribute boottime | ||
82 | */ | ||
83 | static ssize_t boottime_get(struct device *dev, | ||
84 | struct device_attribute *attr, char *buf) | ||
85 | { | ||
86 | struct mrvl_mesh_defaults defs; | ||
87 | int ret; | ||
88 | |||
89 | ret = mesh_get_default_parameters(dev, &defs); | ||
90 | |||
91 | if (ret) | ||
92 | return ret; | ||
93 | |||
94 | return snprintf(buf, 12, "0x%x\n", defs.boottime); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * @brief Set function for sysfs attribute boottime | ||
99 | */ | ||
100 | static ssize_t boottime_set(struct device *dev, | ||
101 | struct device_attribute *attr, const char *buf, size_t count) | ||
102 | { | ||
103 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
104 | struct cmd_ds_mesh_config cmd; | ||
105 | uint32_t datum; | ||
106 | int ret; | ||
107 | |||
108 | memset(&cmd, 0, sizeof(cmd)); | ||
109 | ret = sscanf(buf, "%x", &datum); | ||
110 | if (ret != 1) | ||
111 | return -EINVAL; | ||
112 | |||
113 | /* A too small boot time will result in the device booting into | ||
114 | * standalone (no-host) mode before the host can take control of it, | ||
115 | * so the change will be hard to revert. This may be a desired | ||
116 | * feature (e.g to configure a very fast boot time for devices that | ||
117 | * will not be attached to a host), but dangerous. So I'm enforcing a | ||
118 | * lower limit of 20 seconds: remove and recompile the driver if this | ||
119 | * does not work for you. | ||
120 | */ | ||
121 | datum = (datum < 20) ? 20 : datum; | ||
122 | cmd.data[0] = datum; | ||
123 | cmd.length = cpu_to_le16(sizeof(uint8_t)); | ||
124 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
125 | CMD_TYPE_MESH_SET_BOOTTIME); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | return strlen(buf); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * @brief Get function for sysfs attribute channel | ||
134 | */ | ||
135 | static ssize_t channel_get(struct device *dev, | ||
136 | struct device_attribute *attr, char *buf) | ||
137 | { | ||
138 | struct mrvl_mesh_defaults defs; | ||
139 | int ret; | ||
140 | |||
141 | ret = mesh_get_default_parameters(dev, &defs); | ||
142 | |||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | return snprintf(buf, 12, "0x%x\n", le16_to_cpu(defs.channel)); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * @brief Set function for sysfs attribute channel | ||
151 | */ | ||
152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, | ||
153 | const char *buf, size_t count) | ||
154 | { | ||
155 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
156 | struct cmd_ds_mesh_config cmd; | ||
157 | uint16_t datum; | ||
158 | int ret; | ||
159 | |||
160 | memset(&cmd, 0, sizeof(cmd)); | ||
161 | ret = sscanf(buf, "%hx", &datum); | ||
162 | if (ret != 1 || datum < 1 || datum > 11) | ||
163 | return -EINVAL; | ||
164 | |||
165 | *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); | ||
166 | cmd.length = cpu_to_le16(sizeof(uint16_t)); | ||
167 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
168 | CMD_TYPE_MESH_SET_DEF_CHANNEL); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | return strlen(buf); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * @brief Get function for sysfs attribute mesh_id | ||
177 | */ | ||
178 | static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, | ||
179 | char *buf) | ||
180 | { | ||
181 | struct mrvl_mesh_defaults defs; | ||
182 | int maxlen; | ||
183 | int ret; | ||
184 | |||
185 | ret = mesh_get_default_parameters(dev, &defs); | ||
186 | |||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) { | ||
191 | lbs_pr_err("inconsistent mesh ID length"); | ||
192 | defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE; | ||
193 | } | ||
194 | |||
195 | /* SSID not null terminated: reserve room for \0 + \n */ | ||
196 | maxlen = defs.meshie.val.mesh_id_len + 2; | ||
197 | maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; | ||
198 | |||
199 | defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; | ||
200 | |||
201 | return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * @brief Set function for sysfs attribute mesh_id | ||
206 | */ | ||
207 | static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | ||
208 | const char *buf, size_t count) | ||
209 | { | ||
210 | struct cmd_ds_mesh_config cmd; | ||
211 | struct mrvl_mesh_defaults defs; | ||
212 | struct mrvl_meshie *ie; | ||
213 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
214 | int len; | ||
215 | int ret; | ||
216 | |||
217 | if (count < 2 || count > IW_ESSID_MAX_SIZE + 1) | ||
218 | return -EINVAL; | ||
219 | |||
220 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
221 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
222 | |||
223 | /* fetch all other Information Element parameters */ | ||
224 | ret = mesh_get_default_parameters(dev, &defs); | ||
225 | |||
226 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
227 | |||
228 | /* transfer IE elements */ | ||
229 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
230 | |||
231 | len = count - 1; | ||
232 | memcpy(ie->val.mesh_id, buf, len); | ||
233 | /* SSID len */ | ||
234 | ie->val.mesh_id_len = len; | ||
235 | /* IE len */ | ||
236 | ie->hdr.len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len; | ||
237 | |||
238 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
239 | CMD_TYPE_MESH_SET_MESH_IE); | ||
240 | if (ret) | ||
241 | return ret; | ||
242 | |||
243 | return strlen(buf); | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * @brief Get function for sysfs attribute protocol_id | ||
248 | */ | ||
249 | static ssize_t protocol_id_get(struct device *dev, | ||
250 | struct device_attribute *attr, char *buf) | ||
251 | { | ||
252 | struct mrvl_mesh_defaults defs; | ||
253 | int ret; | ||
254 | |||
255 | ret = mesh_get_default_parameters(dev, &defs); | ||
256 | |||
257 | if (ret) | ||
258 | return ret; | ||
259 | |||
260 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * @brief Set function for sysfs attribute protocol_id | ||
265 | */ | ||
266 | static ssize_t protocol_id_set(struct device *dev, | ||
267 | struct device_attribute *attr, const char *buf, size_t count) | ||
268 | { | ||
269 | struct cmd_ds_mesh_config cmd; | ||
270 | struct mrvl_mesh_defaults defs; | ||
271 | struct mrvl_meshie *ie; | ||
272 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
273 | uint32_t datum; | ||
274 | int ret; | ||
275 | |||
276 | memset(&cmd, 0, sizeof(cmd)); | ||
277 | ret = sscanf(buf, "%x", &datum); | ||
278 | if (ret != 1) | ||
279 | return -EINVAL; | ||
280 | |||
281 | /* fetch all other Information Element parameters */ | ||
282 | ret = mesh_get_default_parameters(dev, &defs); | ||
283 | |||
284 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
285 | |||
286 | /* transfer IE elements */ | ||
287 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
288 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
289 | /* update protocol id */ | ||
290 | ie->val.active_protocol_id = datum; | ||
291 | |||
292 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
293 | CMD_TYPE_MESH_SET_MESH_IE); | ||
294 | if (ret) | ||
295 | return ret; | ||
296 | |||
297 | return strlen(buf); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * @brief Get function for sysfs attribute metric_id | ||
302 | */ | ||
303 | static ssize_t metric_id_get(struct device *dev, | ||
304 | struct device_attribute *attr, char *buf) | ||
305 | { | ||
306 | struct mrvl_mesh_defaults defs; | ||
307 | int ret; | ||
308 | |||
309 | ret = mesh_get_default_parameters(dev, &defs); | ||
310 | |||
311 | if (ret) | ||
312 | return ret; | ||
313 | |||
314 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * @brief Set function for sysfs attribute metric_id | ||
319 | */ | ||
320 | static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, | ||
321 | const char *buf, size_t count) | ||
322 | { | ||
323 | struct cmd_ds_mesh_config cmd; | ||
324 | struct mrvl_mesh_defaults defs; | ||
325 | struct mrvl_meshie *ie; | ||
326 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
327 | uint32_t datum; | ||
328 | int ret; | ||
329 | |||
330 | memset(&cmd, 0, sizeof(cmd)); | ||
331 | ret = sscanf(buf, "%x", &datum); | ||
332 | if (ret != 1) | ||
333 | return -EINVAL; | ||
334 | |||
335 | /* fetch all other Information Element parameters */ | ||
336 | ret = mesh_get_default_parameters(dev, &defs); | ||
337 | |||
338 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
339 | |||
340 | /* transfer IE elements */ | ||
341 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
342 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
343 | /* update metric id */ | ||
344 | ie->val.active_metric_id = datum; | ||
345 | |||
346 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
347 | CMD_TYPE_MESH_SET_MESH_IE); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | |||
351 | return strlen(buf); | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * @brief Get function for sysfs attribute capability | ||
356 | */ | ||
357 | static ssize_t capability_get(struct device *dev, | ||
358 | struct device_attribute *attr, char *buf) | ||
359 | { | ||
360 | struct mrvl_mesh_defaults defs; | ||
361 | int ret; | ||
362 | |||
363 | ret = mesh_get_default_parameters(dev, &defs); | ||
364 | |||
365 | if (ret) | ||
366 | return ret; | ||
367 | |||
368 | return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * @brief Set function for sysfs attribute capability | ||
373 | */ | ||
374 | static ssize_t capability_set(struct device *dev, struct device_attribute *attr, | ||
375 | const char *buf, size_t count) | ||
376 | { | ||
377 | struct cmd_ds_mesh_config cmd; | ||
378 | struct mrvl_mesh_defaults defs; | ||
379 | struct mrvl_meshie *ie; | ||
380 | struct lbs_private *priv = to_net_dev(dev)->priv; | ||
381 | uint32_t datum; | ||
382 | int ret; | ||
383 | |||
384 | memset(&cmd, 0, sizeof(cmd)); | ||
385 | ret = sscanf(buf, "%x", &datum); | ||
386 | if (ret != 1) | ||
387 | return -EINVAL; | ||
388 | |||
389 | /* fetch all other Information Element parameters */ | ||
390 | ret = mesh_get_default_parameters(dev, &defs); | ||
391 | |||
392 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
393 | |||
394 | /* transfer IE elements */ | ||
395 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
396 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
397 | /* update value */ | ||
398 | ie->val.mesh_capability = datum; | ||
399 | |||
400 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
401 | CMD_TYPE_MESH_SET_MESH_IE); | ||
402 | if (ret) | ||
403 | return ret; | ||
404 | |||
405 | return strlen(buf); | ||
406 | } | ||
407 | |||
408 | |||
409 | static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set); | ||
410 | static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set); | ||
411 | static DEVICE_ATTR(channel, 0644, channel_get, channel_set); | ||
412 | static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set); | ||
413 | static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set); | ||
414 | static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set); | ||
415 | static DEVICE_ATTR(capability, 0644, capability_get, capability_set); | ||
416 | |||
417 | static struct attribute *boot_opts_attrs[] = { | ||
418 | &dev_attr_bootflag.attr, | ||
419 | &dev_attr_boottime.attr, | ||
420 | &dev_attr_channel.attr, | ||
421 | NULL | ||
422 | }; | ||
423 | |||
424 | static struct attribute_group boot_opts_group = { | ||
425 | .name = "boot_options", | ||
426 | .attrs = boot_opts_attrs, | ||
427 | }; | ||
428 | |||
429 | static struct attribute *mesh_ie_attrs[] = { | ||
430 | &dev_attr_mesh_id.attr, | ||
431 | &dev_attr_protocol_id.attr, | ||
432 | &dev_attr_metric_id.attr, | ||
433 | &dev_attr_capability.attr, | ||
434 | NULL | ||
435 | }; | ||
436 | |||
437 | static struct attribute_group mesh_ie_group = { | ||
438 | .name = "mesh_ie", | ||
439 | .attrs = mesh_ie_attrs, | ||
440 | }; | ||
441 | |||
442 | void lbs_persist_config_init(struct net_device *dev) | ||
443 | { | ||
444 | int ret; | ||
445 | ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); | ||
446 | ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); | ||
447 | } | ||
448 | |||
449 | void lbs_persist_config_remove(struct net_device *dev) | ||
450 | { | ||
451 | sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); | ||
452 | sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); | ||
453 | } | ||
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 05af7316f698..5749f22b296f 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -237,7 +237,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
237 | /* Take the data rate from the rxpd structure | 237 | /* Take the data rate from the rxpd structure |
238 | * only if the rate is auto | 238 | * only if the rate is auto |
239 | */ | 239 | */ |
240 | if (priv->auto_rate) | 240 | if (priv->enablehwauto) |
241 | priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); | 241 | priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); |
242 | 242 | ||
243 | lbs_compute_rssi(priv, p_rx_pd); | 243 | lbs_compute_rssi(priv, p_rx_pd); |
@@ -383,7 +383,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
383 | /* Take the data rate from the rxpd structure | 383 | /* Take the data rate from the rxpd structure |
384 | * only if the rate is auto | 384 | * only if the rate is auto |
385 | */ | 385 | */ |
386 | if (priv->auto_rate) | 386 | if (priv->enablehwauto) |
387 | priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); | 387 | priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); |
388 | 388 | ||
389 | lbs_compute_rssi(priv, prxpd); | 389 | lbs_compute_rssi(priv, prxpd); |
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 4031be420862..e0c2599da92f 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | #include <linux/if_ether.h> | 7 | #include <linux/if_ether.h> |
8 | #include <asm/byteorder.h> | 8 | #include <asm/byteorder.h> |
9 | #include <linux/wireless.h> | ||
10 | #include <net/ieee80211.h> | ||
9 | 11 | ||
10 | struct ieeetypes_cfparamset { | 12 | struct ieeetypes_cfparamset { |
11 | u8 elementid; | 13 | u8 elementid; |
@@ -252,4 +254,32 @@ struct mrvlietypes_ledbhv { | |||
252 | struct led_bhv ledbhv[1]; | 254 | struct led_bhv ledbhv[1]; |
253 | } __attribute__ ((packed)); | 255 | } __attribute__ ((packed)); |
254 | 256 | ||
257 | /* Meant to be packed as the value member of a struct ieee80211_info_element. | ||
258 | * Note that the len member of the ieee80211_info_element varies depending on | ||
259 | * the mesh_id_len */ | ||
260 | struct mrvl_meshie_val { | ||
261 | uint8_t oui[P80211_OUI_LEN]; | ||
262 | uint8_t type; | ||
263 | uint8_t subtype; | ||
264 | uint8_t version; | ||
265 | uint8_t active_protocol_id; | ||
266 | uint8_t active_metric_id; | ||
267 | uint8_t mesh_capability; | ||
268 | uint8_t mesh_id_len; | ||
269 | uint8_t mesh_id[IW_ESSID_MAX_SIZE]; | ||
270 | } __attribute__ ((packed)); | ||
271 | |||
272 | struct mrvl_meshie { | ||
273 | struct ieee80211_info_element hdr; | ||
274 | struct mrvl_meshie_val val; | ||
275 | } __attribute__ ((packed)); | ||
276 | |||
277 | struct mrvl_mesh_defaults { | ||
278 | __le32 bootflag; | ||
279 | uint8_t boottime; | ||
280 | uint8_t reserved; | ||
281 | __le16 channel; | ||
282 | struct mrvl_meshie meshie; | ||
283 | } __attribute__ ((packed)); | ||
284 | |||
255 | #endif | 285 | #endif |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 0973d015a520..8b3ed77860b3 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -1002,7 +1002,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
1002 | else if (priv->mode == IW_MODE_ADHOC) | 1002 | else if (priv->mode == IW_MODE_ADHOC) |
1003 | lbs_stop_adhoc_network(priv); | 1003 | lbs_stop_adhoc_network(priv); |
1004 | } | 1004 | } |
1005 | lbs_mesh_config(priv, 1, fwrq->m); | 1005 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); |
1006 | lbs_update_channel(priv); | 1006 | lbs_update_channel(priv); |
1007 | ret = 0; | 1007 | ret = 0; |
1008 | 1008 | ||
@@ -1021,29 +1021,38 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | |||
1021 | 1021 | ||
1022 | lbs_deb_enter(LBS_DEB_WEXT); | 1022 | lbs_deb_enter(LBS_DEB_WEXT); |
1023 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); | 1023 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); |
1024 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); | ||
1025 | |||
1026 | if (vwrq->fixed && vwrq->value == -1) | ||
1027 | goto out; | ||
1024 | 1028 | ||
1025 | /* Auto rate? */ | 1029 | /* Auto rate? */ |
1026 | if (vwrq->value == -1) { | 1030 | priv->enablehwauto = !vwrq->fixed; |
1027 | priv->auto_rate = 1; | 1031 | |
1032 | if (vwrq->value == -1) | ||
1028 | priv->cur_rate = 0; | 1033 | priv->cur_rate = 0; |
1029 | } else { | 1034 | else { |
1030 | if (vwrq->value % 100000) | 1035 | if (vwrq->value % 100000) |
1031 | goto out; | 1036 | goto out; |
1032 | 1037 | ||
1038 | new_rate = vwrq->value / 500000; | ||
1039 | priv->cur_rate = new_rate; | ||
1040 | /* the rest is only needed for lbs_set_data_rate() */ | ||
1033 | memset(rates, 0, sizeof(rates)); | 1041 | memset(rates, 0, sizeof(rates)); |
1034 | copy_active_data_rates(priv, rates); | 1042 | copy_active_data_rates(priv, rates); |
1035 | new_rate = vwrq->value / 500000; | ||
1036 | if (!memchr(rates, new_rate, sizeof(rates))) { | 1043 | if (!memchr(rates, new_rate, sizeof(rates))) { |
1037 | lbs_pr_alert("fixed data rate 0x%X out of range\n", | 1044 | lbs_pr_alert("fixed data rate 0x%X out of range\n", |
1038 | new_rate); | 1045 | new_rate); |
1039 | goto out; | 1046 | goto out; |
1040 | } | 1047 | } |
1041 | |||
1042 | priv->cur_rate = new_rate; | ||
1043 | priv->auto_rate = 0; | ||
1044 | } | 1048 | } |
1045 | 1049 | ||
1046 | ret = lbs_set_data_rate(priv, new_rate); | 1050 | /* Try the newer command first (Firmware Spec 5.1 and above) */ |
1051 | ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET); | ||
1052 | |||
1053 | /* Fallback to older version */ | ||
1054 | if (ret) | ||
1055 | ret = lbs_set_data_rate(priv, new_rate); | ||
1047 | 1056 | ||
1048 | out: | 1057 | out: |
1049 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 1058 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
@@ -1060,7 +1069,7 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, | |||
1060 | if (priv->connect_status == LBS_CONNECTED) { | 1069 | if (priv->connect_status == LBS_CONNECTED) { |
1061 | vwrq->value = priv->cur_rate * 500000; | 1070 | vwrq->value = priv->cur_rate * 500000; |
1062 | 1071 | ||
1063 | if (priv->auto_rate) | 1072 | if (priv->enablehwauto) |
1064 | vwrq->fixed = 0; | 1073 | vwrq->fixed = 0; |
1065 | else | 1074 | else |
1066 | vwrq->fixed = 1; | 1075 | vwrq->fixed = 1; |
@@ -2011,7 +2020,8 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2011 | priv->mesh_ssid_len = dwrq->length; | 2020 | priv->mesh_ssid_len = dwrq->length; |
2012 | } | 2021 | } |
2013 | 2022 | ||
2014 | lbs_mesh_config(priv, 1, priv->curbssparams.channel); | 2023 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
2024 | priv->curbssparams.channel); | ||
2015 | out: | 2025 | out: |
2016 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 2026 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
2017 | return ret; | 2027 | return ret; |