diff options
Diffstat (limited to 'drivers/net/wireless/libertas/cfg.c')
-rw-r--r-- | drivers/net/wireless/libertas/cfg.c | 62 |
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 | |||
1178 | done: | 1216 | done: |
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; |