aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/cfg.c')
-rw-r--r--drivers/net/wireless/libertas/cfg.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 3e82f1627209..317f086ced0a 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -10,6 +10,7 @@
10#include <linux/wait.h> 10#include <linux/wait.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/wait.h>
13#include <linux/ieee80211.h> 14#include <linux/ieee80211.h>
14#include <net/cfg80211.h> 15#include <net/cfg80211.h>
15#include <asm/unaligned.h> 16#include <asm/unaligned.h>
@@ -526,20 +527,31 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
526 527
527 pos = scanresp->bssdesc_and_tlvbuffer; 528 pos = scanresp->bssdesc_and_tlvbuffer;
528 529
530 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer,
531 scanresp->bssdescriptsize);
532
529 tsfdesc = pos + bsssize; 533 tsfdesc = pos + bsssize;
530 tsfsize = 4 + 8 * scanresp->nr_sets; 534 tsfsize = 4 + 8 * scanresp->nr_sets;
535 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize);
531 536
532 /* Validity check: we expect a Marvell-Local TLV */ 537 /* Validity check: we expect a Marvell-Local TLV */
533 i = get_unaligned_le16(tsfdesc); 538 i = get_unaligned_le16(tsfdesc);
534 tsfdesc += 2; 539 tsfdesc += 2;
535 if (i != TLV_TYPE_TSFTIMESTAMP) 540 if (i != TLV_TYPE_TSFTIMESTAMP) {
541 lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i);
536 goto done; 542 goto done;
543 }
544
537 /* Validity check: the TLV holds TSF values with 8 bytes each, so 545 /* Validity check: the TLV holds TSF values with 8 bytes each, so
538 * the size in the TLV must match the nr_sets value */ 546 * the size in the TLV must match the nr_sets value */
539 i = get_unaligned_le16(tsfdesc); 547 i = get_unaligned_le16(tsfdesc);
540 tsfdesc += 2; 548 tsfdesc += 2;
541 if (i / 8 != scanresp->nr_sets) 549 if (i / 8 != scanresp->nr_sets) {
550 lbs_deb_scan("scan response: invalid number of TSF timestamp "
551 "sets (expected %d got %d)\n", scanresp->nr_sets,
552 i / 8);
542 goto done; 553 goto done;
554 }
543 555
544 for (i = 0; i < scanresp->nr_sets; i++) { 556 for (i = 0; i < scanresp->nr_sets; i++) {
545 const u8 *bssid; 557 const u8 *bssid;
@@ -581,8 +593,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
581 id = *pos++; 593 id = *pos++;
582 elen = *pos++; 594 elen = *pos++;
583 left -= 2; 595 left -= 2;
584 if (elen > left || elen == 0) 596 if (elen > left || elen == 0) {
597 lbs_deb_scan("scan response: invalid IE fmt\n");
585 goto done; 598 goto done;
599 }
600
586 if (id == WLAN_EID_DS_PARAMS) 601 if (id == WLAN_EID_DS_PARAMS)
587 chan_no = *pos; 602 chan_no = *pos;
588 if (id == WLAN_EID_SSID) { 603 if (id == WLAN_EID_SSID) {
@@ -613,7 +628,9 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
613 capa, intvl, ie, ielen, 628 capa, intvl, ie, ielen,
614 LBS_SCAN_RSSI_TO_MBM(rssi), 629 LBS_SCAN_RSSI_TO_MBM(rssi),
615 GFP_KERNEL); 630 GFP_KERNEL);
616 } 631 } else
632 lbs_deb_scan("scan response: missing BSS channel IE\n");
633
617 tsfdesc += 8; 634 tsfdesc += 8;
618 } 635 }
619 ret = 0; 636 ret = 0;
@@ -1103,7 +1120,7 @@ static int lbs_associate(struct lbs_private *priv,
1103 lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); 1120 lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp);
1104 1121
1105 /* add auth type TLV */ 1122 /* add auth type TLV */
1106 if (priv->fwrelease >= 0x09000000) 1123 if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9)
1107 pos += lbs_add_auth_type_tlv(pos, sme->auth_type); 1124 pos += lbs_add_auth_type_tlv(pos, sme->auth_type);
1108 1125
1109 /* add WPA/WPA2 TLV */ 1126 /* add WPA/WPA2 TLV */
@@ -1114,6 +1131,9 @@ static int lbs_associate(struct lbs_private *priv,
1114 (u16)(pos - (u8 *) &cmd->iebuf); 1131 (u16)(pos - (u8 *) &cmd->iebuf);
1115 cmd->hdr.size = cpu_to_le16(len); 1132 cmd->hdr.size = cpu_to_le16(len);
1116 1133
1134 lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd,
1135 le16_to_cpu(cmd->hdr.size));
1136
1117 /* store for later use */ 1137 /* store for later use */
1118 memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); 1138 memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
1119 1139
@@ -1121,14 +1141,28 @@ static int lbs_associate(struct lbs_private *priv,
1121 if (ret) 1141 if (ret)
1122 goto done; 1142 goto done;
1123 1143
1124
1125 /* generate connect message to cfg80211 */ 1144 /* generate connect message to cfg80211 */
1126 1145
1127 resp = (void *) cmd; /* recast for easier field access */ 1146 resp = (void *) cmd; /* recast for easier field access */
1128 status = le16_to_cpu(resp->statuscode); 1147 status = le16_to_cpu(resp->statuscode);
1129 1148
1130 /* Convert statis code of old firmware */ 1149 /* Older FW versions map the IEEE 802.11 Status Code in the association
1131 if (priv->fwrelease < 0x09000000) 1150 * response to the following values returned in resp->statuscode:
1151 *
1152 * IEEE Status Code Marvell Status Code
1153 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
1154 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1155 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1156 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1157 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1158 * others -> 0x0003 ASSOC_RESULT_REFUSED
1159 *
1160 * Other response codes:
1161 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
1162 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
1163 * association response from the AP)
1164 */
1165 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
1132 switch (status) { 1166 switch (status) {
1133 case 0: 1167 case 0:
1134 break; 1168 break;
@@ -1150,11 +1184,16 @@ static int lbs_associate(struct lbs_private *priv,
1150 break; 1184 break;
1151 default: 1185 default:
1152 lbs_deb_assoc("association failure %d\n", status); 1186 lbs_deb_assoc("association failure %d\n", status);
1153 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 1187 /* v5 OLPC firmware does return the AP status code if
1188 * it's not one of the values above. Let that through.
1189 */
1190 break;
1191 }
1154 } 1192 }
1155 1193
1156 lbs_deb_assoc("status %d, capability 0x%04x\n", status, 1194 lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, "
1157 le16_to_cpu(resp->capability)); 1195 "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode),
1196 le16_to_cpu(resp->capability), le16_to_cpu(resp->aid));
1158 1197
1159 resp_ie_len = le16_to_cpu(resp->hdr.size) 1198 resp_ie_len = le16_to_cpu(resp->hdr.size)
1160 - sizeof(resp->hdr) 1199 - sizeof(resp->hdr)
@@ -1174,7 +1213,6 @@ static int lbs_associate(struct lbs_private *priv,
1174 netif_tx_wake_all_queues(priv->dev); 1213 netif_tx_wake_all_queues(priv->dev);
1175 } 1214 }
1176 1215
1177
1178done: 1216done:
1179 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 1217 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1180 return ret; 1218 return ret;