diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-08-25 14:51:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-25 14:51:42 -0400 |
commit | e569aa78ba01f7f66e016a4d57310fd041524d17 (patch) | |
tree | eaedc03d42ee2bf6200fc07b080a99bad103def3 /drivers/net/wireless/libertas | |
parent | 4562487a00445eab96311365ba15c41dc4d043cd (diff) | |
parent | 268bae0b6879f238ba57f5f801958d1254e136f7 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/libertas/if_sdio.c
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r-- | drivers/net/wireless/libertas/cfg.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 130 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 161 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 150 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 105 |
10 files changed, 429 insertions, 262 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; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 1d141fefd767..2ae752d10065 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -8,7 +8,14 @@ | |||
8 | #define _LBS_DECL_H_ | 8 | #define _LBS_DECL_H_ |
9 | 9 | ||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/firmware.h> | ||
11 | 12 | ||
13 | /* Should be terminated by a NULL entry */ | ||
14 | struct lbs_fw_table { | ||
15 | int model; | ||
16 | const char *helper; | ||
17 | const char *fwname; | ||
18 | }; | ||
12 | 19 | ||
13 | struct lbs_private; | 20 | struct lbs_private; |
14 | struct sk_buff; | 21 | struct sk_buff; |
@@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | |||
53 | u32 lbs_fw_index_to_data_rate(u8 index); | 60 | u32 lbs_fw_index_to_data_rate(u8 index); |
54 | u8 lbs_data_rate_to_fw_index(u32 rate); | 61 | u8 lbs_data_rate_to_fw_index(u32 rate); |
55 | 62 | ||
63 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
64 | const char *user_mainfw, u32 card_model, | ||
65 | const struct lbs_fw_table *fw_table, | ||
66 | const struct firmware **helper, | ||
67 | const struct firmware **mainfw); | ||
68 | |||
56 | #endif | 69 | #endif |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 9c298396be50..e213a5dc049d 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -48,7 +48,6 @@ | |||
48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); | 48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); |
49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); | 49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
52 | 51 | ||
53 | 52 | ||
54 | 53 | ||
@@ -61,9 +60,34 @@ struct if_cs_card { | |||
61 | struct lbs_private *priv; | 60 | struct lbs_private *priv; |
62 | void __iomem *iobase; | 61 | void __iomem *iobase; |
63 | bool align_regs; | 62 | bool align_regs; |
63 | u32 model; | ||
64 | }; | 64 | }; |
65 | 65 | ||
66 | 66 | ||
67 | enum { | ||
68 | MODEL_UNKNOWN = 0x00, | ||
69 | MODEL_8305 = 0x01, | ||
70 | MODEL_8381 = 0x02, | ||
71 | MODEL_8385 = 0x03 | ||
72 | }; | ||
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8305, "libertas/cf8305.bin", NULL }, | ||
76 | { MODEL_8305, "libertas_cs_helper.fw", NULL }, | ||
77 | { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" }, | ||
78 | { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
79 | { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" }, | ||
80 | { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
81 | { 0, NULL, NULL } | ||
82 | }; | ||
83 | MODULE_FIRMWARE("libertas/cf8305.bin"); | ||
84 | MODULE_FIRMWARE("libertas/cf8381_helper.bin"); | ||
85 | MODULE_FIRMWARE("libertas/cf8381.bin"); | ||
86 | MODULE_FIRMWARE("libertas/cf8385_helper.bin"); | ||
87 | MODULE_FIRMWARE("libertas/cf8385.bin"); | ||
88 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
89 | MODULE_FIRMWARE("libertas_cs.fw"); | ||
90 | |||
67 | 91 | ||
68 | /********************************************************************/ | 92 | /********************************************************************/ |
69 | /* Hardware access */ | 93 | /* Hardware access */ |
@@ -289,22 +313,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
289 | #define CF8385_MANFID 0x02df | 313 | #define CF8385_MANFID 0x02df |
290 | #define CF8385_CARDID 0x8103 | 314 | #define CF8385_CARDID 0x8103 |
291 | 315 | ||
292 | static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) | 316 | /* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when |
293 | { | 317 | * that gets fixed. Currently there's no way to access it from the probe hook. |
294 | return (p_dev->manf_id == CF8305_MANFID && | 318 | */ |
295 | p_dev->card_id == CF8305_CARDID); | 319 | static inline u32 get_model(u16 manf_id, u16 card_id) |
296 | } | ||
297 | |||
298 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) | ||
299 | { | ||
300 | return (p_dev->manf_id == CF8381_MANFID && | ||
301 | p_dev->card_id == CF8381_CARDID); | ||
302 | } | ||
303 | |||
304 | static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) | ||
305 | { | 320 | { |
306 | return (p_dev->manf_id == CF8385_MANFID && | 321 | /* NOTE: keep in sync with if_cs_ids */ |
307 | p_dev->card_id == CF8385_CARDID); | 322 | if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID) |
323 | return MODEL_8305; | ||
324 | else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID) | ||
325 | return MODEL_8381; | ||
326 | else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID) | ||
327 | return MODEL_8385; | ||
328 | return MODEL_UNKNOWN; | ||
308 | } | 329 | } |
309 | 330 | ||
310 | /********************************************************************/ | 331 | /********************************************************************/ |
@@ -558,12 +579,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
558 | * | 579 | * |
559 | * Return 0 on success | 580 | * Return 0 on success |
560 | */ | 581 | */ |
561 | static int if_cs_prog_helper(struct if_cs_card *card) | 582 | static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) |
562 | { | 583 | { |
563 | int ret = 0; | 584 | int ret = 0; |
564 | int sent = 0; | 585 | int sent = 0; |
565 | u8 scratch; | 586 | u8 scratch; |
566 | const struct firmware *fw; | ||
567 | 587 | ||
568 | lbs_deb_enter(LBS_DEB_CS); | 588 | lbs_deb_enter(LBS_DEB_CS); |
569 | 589 | ||
@@ -589,14 +609,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
589 | goto done; | 609 | goto done; |
590 | } | 610 | } |
591 | 611 | ||
592 | /* TODO: make firmware file configurable */ | ||
593 | ret = request_firmware(&fw, "libertas_cs_helper.fw", | ||
594 | &card->p_dev->dev); | ||
595 | if (ret) { | ||
596 | lbs_pr_err("can't load helper firmware\n"); | ||
597 | ret = -ENODEV; | ||
598 | goto done; | ||
599 | } | ||
600 | lbs_deb_cs("helper size %td\n", fw->size); | 612 | lbs_deb_cs("helper size %td\n", fw->size); |
601 | 613 | ||
602 | /* "Set the 5 bytes of the helper image to 0" */ | 614 | /* "Set the 5 bytes of the helper image to 0" */ |
@@ -635,7 +647,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
635 | if (ret < 0) { | 647 | if (ret < 0) { |
636 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 648 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", |
637 | sent, ret); | 649 | sent, ret); |
638 | goto err_release; | 650 | goto done; |
639 | } | 651 | } |
640 | 652 | ||
641 | if (count == 0) | 653 | if (count == 0) |
@@ -644,17 +656,14 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
644 | sent += count; | 656 | sent += count; |
645 | } | 657 | } |
646 | 658 | ||
647 | err_release: | ||
648 | release_firmware(fw); | ||
649 | done: | 659 | done: |
650 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 660 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
651 | return ret; | 661 | return ret; |
652 | } | 662 | } |
653 | 663 | ||
654 | 664 | ||
655 | static int if_cs_prog_real(struct if_cs_card *card) | 665 | static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) |
656 | { | 666 | { |
657 | const struct firmware *fw; | ||
658 | int ret = 0; | 667 | int ret = 0; |
659 | int retry = 0; | 668 | int retry = 0; |
660 | int len = 0; | 669 | int len = 0; |
@@ -662,21 +671,13 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
662 | 671 | ||
663 | lbs_deb_enter(LBS_DEB_CS); | 672 | lbs_deb_enter(LBS_DEB_CS); |
664 | 673 | ||
665 | /* TODO: make firmware file configurable */ | ||
666 | ret = request_firmware(&fw, "libertas_cs.fw", | ||
667 | &card->p_dev->dev); | ||
668 | if (ret) { | ||
669 | lbs_pr_err("can't load firmware\n"); | ||
670 | ret = -ENODEV; | ||
671 | goto done; | ||
672 | } | ||
673 | lbs_deb_cs("fw size %td\n", fw->size); | 674 | lbs_deb_cs("fw size %td\n", fw->size); |
674 | 675 | ||
675 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, | 676 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, |
676 | IF_CS_SQ_HELPER_OK); | 677 | IF_CS_SQ_HELPER_OK); |
677 | if (ret < 0) { | 678 | if (ret < 0) { |
678 | lbs_pr_err("helper firmware doesn't answer\n"); | 679 | lbs_pr_err("helper firmware doesn't answer\n"); |
679 | goto err_release; | 680 | goto done; |
680 | } | 681 | } |
681 | 682 | ||
682 | for (sent = 0; sent < fw->size; sent += len) { | 683 | for (sent = 0; sent < fw->size; sent += len) { |
@@ -691,7 +692,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
691 | if (retry > 20) { | 692 | if (retry > 20) { |
692 | lbs_pr_err("could not download firmware\n"); | 693 | lbs_pr_err("could not download firmware\n"); |
693 | ret = -ENODEV; | 694 | ret = -ENODEV; |
694 | goto err_release; | 695 | goto done; |
695 | } | 696 | } |
696 | if (retry) { | 697 | if (retry) { |
697 | sent -= len; | 698 | sent -= len; |
@@ -710,7 +711,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
710 | IF_CS_BIT_COMMAND); | 711 | IF_CS_BIT_COMMAND); |
711 | if (ret < 0) { | 712 | if (ret < 0) { |
712 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 713 | lbs_pr_err("can't download firmware at 0x%x\n", sent); |
713 | goto err_release; | 714 | goto done; |
714 | } | 715 | } |
715 | } | 716 | } |
716 | 717 | ||
@@ -718,9 +719,6 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
718 | if (ret < 0) | 719 | if (ret < 0) |
719 | lbs_pr_err("firmware download failed\n"); | 720 | lbs_pr_err("firmware download failed\n"); |
720 | 721 | ||
721 | err_release: | ||
722 | release_firmware(fw); | ||
723 | |||
724 | done: | 722 | done: |
725 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 723 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
726 | return ret; | 724 | return ret; |
@@ -824,6 +822,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
824 | unsigned int prod_id; | 822 | unsigned int prod_id; |
825 | struct lbs_private *priv; | 823 | struct lbs_private *priv; |
826 | struct if_cs_card *card; | 824 | struct if_cs_card *card; |
825 | const struct firmware *helper = NULL; | ||
826 | const struct firmware *mainfw = NULL; | ||
827 | 827 | ||
828 | lbs_deb_enter(LBS_DEB_CS); | 828 | lbs_deb_enter(LBS_DEB_CS); |
829 | 829 | ||
@@ -843,7 +843,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
843 | goto out1; | 843 | goto out1; |
844 | } | 844 | } |
845 | 845 | ||
846 | |||
847 | /* | 846 | /* |
848 | * Allocate an interrupt line. Note that this does not assign | 847 | * Allocate an interrupt line. Note that this does not assign |
849 | * a handler to the interrupt, unless the 'Handler' member of | 848 | * a handler to the interrupt, unless the 'Handler' member of |
@@ -881,34 +880,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
881 | */ | 880 | */ |
882 | card->align_regs = 0; | 881 | card->align_regs = 0; |
883 | 882 | ||
883 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | ||
884 | if (card->model == MODEL_UNKNOWN) { | ||
885 | lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", | ||
886 | p_dev->manf_id, p_dev->card_id); | ||
887 | goto out2; | ||
888 | } | ||
889 | |||
884 | /* Check if we have a current silicon */ | 890 | /* Check if we have a current silicon */ |
885 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | 891 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); |
886 | if (if_cs_hw_is_cf8305(p_dev)) { | 892 | if (card->model == MODEL_8305) { |
887 | card->align_regs = 1; | 893 | card->align_regs = 1; |
888 | if (prod_id < IF_CS_CF8305_B1_REV) { | 894 | if (prod_id < IF_CS_CF8305_B1_REV) { |
889 | lbs_pr_err("old chips like 8305 rev B3 " | 895 | lbs_pr_err("8305 rev B0 and older are not supported\n"); |
890 | "aren't supported\n"); | ||
891 | ret = -ENODEV; | 896 | ret = -ENODEV; |
892 | goto out2; | 897 | goto out2; |
893 | } | 898 | } |
894 | } | 899 | } |
895 | 900 | ||
896 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { | 901 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { |
897 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); | 902 | lbs_pr_err("8381 rev B2 and older are not supported\n"); |
898 | ret = -ENODEV; | 903 | ret = -ENODEV; |
899 | goto out2; | 904 | goto out2; |
900 | } | 905 | } |
901 | 906 | ||
902 | if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { | 907 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { |
903 | lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); | 908 | lbs_pr_err("8385 rev B0 and older are not supported\n"); |
904 | ret = -ENODEV; | 909 | ret = -ENODEV; |
905 | goto out2; | 910 | goto out2; |
906 | } | 911 | } |
907 | 912 | ||
913 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | ||
914 | &fw_table[0], &helper, &mainfw); | ||
915 | if (ret) { | ||
916 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
917 | goto out2; | ||
918 | } | ||
919 | |||
908 | /* Load the firmware early, before calling into libertas.ko */ | 920 | /* Load the firmware early, before calling into libertas.ko */ |
909 | ret = if_cs_prog_helper(card); | 921 | ret = if_cs_prog_helper(card, helper); |
910 | if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) | 922 | if (ret == 0 && (card->model != MODEL_8305)) |
911 | ret = if_cs_prog_real(card); | 923 | ret = if_cs_prog_real(card, mainfw); |
912 | if (ret) | 924 | if (ret) |
913 | goto out2; | 925 | goto out2; |
914 | 926 | ||
@@ -957,6 +969,11 @@ out2: | |||
957 | out1: | 969 | out1: |
958 | pcmcia_disable_device(p_dev); | 970 | pcmcia_disable_device(p_dev); |
959 | out: | 971 | out: |
972 | if (helper) | ||
973 | release_firmware(helper); | ||
974 | if (mainfw) | ||
975 | release_firmware(mainfw); | ||
976 | |||
960 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 977 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
961 | return ret; | 978 | return ret; |
962 | } | 979 | } |
@@ -993,6 +1010,7 @@ static struct pcmcia_device_id if_cs_ids[] = { | |||
993 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), | 1010 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), |
994 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), | 1011 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), |
995 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), | 1012 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), |
1013 | /* NOTE: keep in sync with get_model() */ | ||
996 | PCMCIA_DEVICE_NULL, | 1014 | PCMCIA_DEVICE_NULL, |
997 | }; | 1015 | }; |
998 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); | 1016 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index ba854c70ab94..1bbaaa44d981 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = { | |||
76 | 76 | ||
77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); | 77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); |
78 | 78 | ||
79 | struct if_sdio_model { | 79 | #define MODEL_8385 0x04 |
80 | int model; | 80 | #define MODEL_8686 0x0b |
81 | const char *helper; | 81 | #define MODEL_8688 0x10 |
82 | const char *firmware; | 82 | |
83 | }; | 83 | static const struct lbs_fw_table fw_table[] = { |
84 | 84 | { MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" }, | |
85 | static struct if_sdio_model if_sdio_models[] = { | 85 | { MODEL_8385, "sd8385_helper.bin", "sd8385.bin" }, |
86 | { | 86 | { MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" }, |
87 | /* 8385 */ | 87 | { MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" }, |
88 | .model = IF_SDIO_MODEL_8385, | 88 | { MODEL_8686, "sd8686_helper.bin", "sd8686.bin" }, |
89 | .helper = "sd8385_helper.bin", | 89 | { MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" }, |
90 | .firmware = "sd8385.bin", | 90 | { MODEL_8688, "sd8688_helper.bin", "sd8688.bin" }, |
91 | }, | 91 | { 0, NULL, NULL } |
92 | { | ||
93 | /* 8686 */ | ||
94 | .model = IF_SDIO_MODEL_8686, | ||
95 | .helper = "sd8686_helper.bin", | ||
96 | .firmware = "sd8686.bin", | ||
97 | }, | ||
98 | { | ||
99 | /* 8688 */ | ||
100 | .model = IF_SDIO_MODEL_8688, | ||
101 | .helper = "sd8688_helper.bin", | ||
102 | .firmware = "sd8688.bin", | ||
103 | }, | ||
104 | }; | 92 | }; |
93 | MODULE_FIRMWARE("libertas/sd8385_helper.bin"); | ||
94 | MODULE_FIRMWARE("libertas/sd8385.bin"); | ||
105 | MODULE_FIRMWARE("sd8385_helper.bin"); | 95 | MODULE_FIRMWARE("sd8385_helper.bin"); |
106 | MODULE_FIRMWARE("sd8385.bin"); | 96 | MODULE_FIRMWARE("sd8385.bin"); |
97 | MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin"); | ||
98 | MODULE_FIRMWARE("libertas/sd8686_v9.bin"); | ||
99 | MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin"); | ||
100 | MODULE_FIRMWARE("libertas/sd8686_v8.bin"); | ||
107 | MODULE_FIRMWARE("sd8686_helper.bin"); | 101 | MODULE_FIRMWARE("sd8686_helper.bin"); |
108 | MODULE_FIRMWARE("sd8686.bin"); | 102 | MODULE_FIRMWARE("sd8686.bin"); |
103 | MODULE_FIRMWARE("libertas/sd8688_helper.bin"); | ||
104 | MODULE_FIRMWARE("libertas/sd8688.bin"); | ||
109 | MODULE_FIRMWARE("sd8688_helper.bin"); | 105 | MODULE_FIRMWARE("sd8688_helper.bin"); |
110 | MODULE_FIRMWARE("sd8688.bin"); | 106 | MODULE_FIRMWARE("sd8688.bin"); |
111 | 107 | ||
@@ -187,11 +183,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) | |||
187 | u16 rx_len; | 183 | u16 rx_len; |
188 | 184 | ||
189 | switch (card->model) { | 185 | switch (card->model) { |
190 | case IF_SDIO_MODEL_8385: | 186 | case MODEL_8385: |
191 | case IF_SDIO_MODEL_8686: | 187 | case MODEL_8686: |
192 | rx_len = if_sdio_read_scratch(card, &ret); | 188 | rx_len = if_sdio_read_scratch(card, &ret); |
193 | break; | 189 | break; |
194 | case IF_SDIO_MODEL_8688: | 190 | case MODEL_8688: |
195 | default: /* for newer chipsets */ | 191 | default: /* for newer chipsets */ |
196 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); | 192 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); |
197 | if (!ret) | 193 | if (!ret) |
@@ -288,7 +284,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
288 | 284 | ||
289 | lbs_deb_enter(LBS_DEB_SDIO); | 285 | lbs_deb_enter(LBS_DEB_SDIO); |
290 | 286 | ||
291 | if (card->model == IF_SDIO_MODEL_8385) { | 287 | if (card->model == MODEL_8385) { |
292 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); | 288 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); |
293 | if (ret) | 289 | if (ret) |
294 | goto out; | 290 | goto out; |
@@ -466,10 +462,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
466 | 462 | ||
467 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) | 463 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) |
468 | 464 | ||
469 | static int if_sdio_prog_helper(struct if_sdio_card *card) | 465 | static int if_sdio_prog_helper(struct if_sdio_card *card, |
466 | const struct firmware *fw) | ||
470 | { | 467 | { |
471 | int ret; | 468 | int ret; |
472 | const struct firmware *fw; | ||
473 | unsigned long timeout; | 469 | unsigned long timeout; |
474 | u8 *chunk_buffer; | 470 | u8 *chunk_buffer; |
475 | u32 chunk_size; | 471 | u32 chunk_size; |
@@ -478,16 +474,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
478 | 474 | ||
479 | lbs_deb_enter(LBS_DEB_SDIO); | 475 | lbs_deb_enter(LBS_DEB_SDIO); |
480 | 476 | ||
481 | ret = request_firmware(&fw, card->helper, &card->func->dev); | ||
482 | if (ret) { | ||
483 | lbs_pr_err("can't load helper firmware\n"); | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | chunk_buffer = kzalloc(64, GFP_KERNEL); | 477 | chunk_buffer = kzalloc(64, GFP_KERNEL); |
488 | if (!chunk_buffer) { | 478 | if (!chunk_buffer) { |
489 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
490 | goto release_fw; | 480 | goto out; |
491 | } | 481 | } |
492 | 482 | ||
493 | sdio_claim_host(card->func); | 483 | sdio_claim_host(card->func); |
@@ -562,22 +552,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
562 | release: | 552 | release: |
563 | sdio_release_host(card->func); | 553 | sdio_release_host(card->func); |
564 | kfree(chunk_buffer); | 554 | kfree(chunk_buffer); |
565 | release_fw: | ||
566 | release_firmware(fw); | ||
567 | 555 | ||
568 | out: | 556 | out: |
569 | if (ret) | 557 | if (ret) |
570 | lbs_pr_err("failed to load helper firmware\n"); | 558 | lbs_pr_err("failed to load helper firmware\n"); |
571 | 559 | ||
572 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 560 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
573 | |||
574 | return ret; | 561 | return ret; |
575 | } | 562 | } |
576 | 563 | ||
577 | static int if_sdio_prog_real(struct if_sdio_card *card) | 564 | static int if_sdio_prog_real(struct if_sdio_card *card, |
565 | const struct firmware *fw) | ||
578 | { | 566 | { |
579 | int ret; | 567 | int ret; |
580 | const struct firmware *fw; | ||
581 | unsigned long timeout; | 568 | unsigned long timeout; |
582 | u8 *chunk_buffer; | 569 | u8 *chunk_buffer; |
583 | u32 chunk_size; | 570 | u32 chunk_size; |
@@ -586,16 +573,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
586 | 573 | ||
587 | lbs_deb_enter(LBS_DEB_SDIO); | 574 | lbs_deb_enter(LBS_DEB_SDIO); |
588 | 575 | ||
589 | ret = request_firmware(&fw, card->firmware, &card->func->dev); | ||
590 | if (ret) { | ||
591 | lbs_pr_err("can't load firmware\n"); | ||
592 | goto out; | ||
593 | } | ||
594 | |||
595 | chunk_buffer = kzalloc(512, GFP_KERNEL); | 576 | chunk_buffer = kzalloc(512, GFP_KERNEL); |
596 | if (!chunk_buffer) { | 577 | if (!chunk_buffer) { |
597 | ret = -ENOMEM; | 578 | ret = -ENOMEM; |
598 | goto release_fw; | 579 | goto out; |
599 | } | 580 | } |
600 | 581 | ||
601 | sdio_claim_host(card->func); | 582 | sdio_claim_host(card->func); |
@@ -685,15 +666,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
685 | release: | 666 | release: |
686 | sdio_release_host(card->func); | 667 | sdio_release_host(card->func); |
687 | kfree(chunk_buffer); | 668 | kfree(chunk_buffer); |
688 | release_fw: | ||
689 | release_firmware(fw); | ||
690 | 669 | ||
691 | out: | 670 | out: |
692 | if (ret) | 671 | if (ret) |
693 | lbs_pr_err("failed to load firmware\n"); | 672 | lbs_pr_err("failed to load firmware\n"); |
694 | 673 | ||
695 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 674 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
696 | |||
697 | return ret; | 675 | return ret; |
698 | } | 676 | } |
699 | 677 | ||
@@ -701,6 +679,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
701 | { | 679 | { |
702 | int ret; | 680 | int ret; |
703 | u16 scratch; | 681 | u16 scratch; |
682 | const struct firmware *helper = NULL; | ||
683 | const struct firmware *mainfw = NULL; | ||
704 | 684 | ||
705 | lbs_deb_enter(LBS_DEB_SDIO); | 685 | lbs_deb_enter(LBS_DEB_SDIO); |
706 | 686 | ||
@@ -718,11 +698,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
718 | goto success; | 698 | goto success; |
719 | } | 699 | } |
720 | 700 | ||
721 | ret = if_sdio_prog_helper(card); | 701 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, |
702 | card->model, &fw_table[0], &helper, &mainfw); | ||
703 | if (ret) { | ||
704 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
705 | goto out; | ||
706 | } | ||
707 | |||
708 | ret = if_sdio_prog_helper(card, helper); | ||
722 | if (ret) | 709 | if (ret) |
723 | goto out; | 710 | goto out; |
724 | 711 | ||
725 | ret = if_sdio_prog_real(card); | 712 | ret = if_sdio_prog_real(card, mainfw); |
726 | if (ret) | 713 | if (ret) |
727 | goto out; | 714 | goto out; |
728 | 715 | ||
@@ -733,8 +720,12 @@ success: | |||
733 | ret = 0; | 720 | ret = 0; |
734 | 721 | ||
735 | out: | 722 | out: |
736 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 723 | if (helper) |
724 | release_firmware(helper); | ||
725 | if (mainfw) | ||
726 | release_firmware(mainfw); | ||
737 | 727 | ||
728 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
738 | return ret; | 729 | return ret; |
739 | } | 730 | } |
740 | 731 | ||
@@ -938,7 +929,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
938 | "ID: %x", &model) == 1) | 929 | "ID: %x", &model) == 1) |
939 | break; | 930 | break; |
940 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { | 931 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { |
941 | model = IF_SDIO_MODEL_8385; | 932 | model = MODEL_8385; |
942 | break; | 933 | break; |
943 | } | 934 | } |
944 | } | 935 | } |
@@ -956,13 +947,13 @@ static int if_sdio_probe(struct sdio_func *func, | |||
956 | card->model = model; | 947 | card->model = model; |
957 | 948 | ||
958 | switch (card->model) { | 949 | switch (card->model) { |
959 | case IF_SDIO_MODEL_8385: | 950 | case MODEL_8385: |
960 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; | 951 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; |
961 | break; | 952 | break; |
962 | case IF_SDIO_MODEL_8686: | 953 | case MODEL_8686: |
963 | card->scratch_reg = IF_SDIO_SCRATCH; | 954 | card->scratch_reg = IF_SDIO_SCRATCH; |
964 | break; | 955 | break; |
965 | case IF_SDIO_MODEL_8688: | 956 | case MODEL_8688: |
966 | default: /* for newer chipsets */ | 957 | default: /* for newer chipsets */ |
967 | card->scratch_reg = IF_SDIO_FW_STATUS; | 958 | card->scratch_reg = IF_SDIO_FW_STATUS; |
968 | break; | 959 | break; |
@@ -972,49 +963,17 @@ static int if_sdio_probe(struct sdio_func *func, | |||
972 | card->workqueue = create_workqueue("libertas_sdio"); | 963 | card->workqueue = create_workqueue("libertas_sdio"); |
973 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); | 964 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); |
974 | 965 | ||
975 | for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { | 966 | /* Check if we support this card */ |
976 | if (card->model == if_sdio_models[i].model) | 967 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
968 | if (card->model == fw_table[i].model) | ||
977 | break; | 969 | break; |
978 | } | 970 | } |
979 | 971 | if (i == ARRAY_SIZE(fw_table)) { | |
980 | if (i == ARRAY_SIZE(if_sdio_models)) { | ||
981 | lbs_pr_err("unknown card model 0x%x\n", card->model); | 972 | lbs_pr_err("unknown card model 0x%x\n", card->model); |
982 | ret = -ENODEV; | 973 | ret = -ENODEV; |
983 | goto free; | 974 | goto free; |
984 | } | 975 | } |
985 | 976 | ||
986 | card->helper = if_sdio_models[i].helper; | ||
987 | card->firmware = if_sdio_models[i].firmware; | ||
988 | |||
989 | kparam_block_sysfs_write(helper_name); | ||
990 | if (lbs_helper_name) { | ||
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
997 | lbs_deb_sdio("overriding helper firmware: %s\n", | ||
998 | lbs_helper_name); | ||
999 | card->helper = helper; | ||
1000 | card->helper_allocated = true; | ||
1001 | } | ||
1002 | kparam_unblock_sysfs_write(helper_name); | ||
1003 | |||
1004 | kparam_block_sysfs_write(fw_name); | ||
1005 | if (lbs_fw_name) { | ||
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | ||
1013 | card->firmware = fw_name; | ||
1014 | card->firmware_allocated = true; | ||
1015 | } | ||
1016 | kparam_unblock_sysfs_write(fw_name); | ||
1017 | |||
1018 | sdio_claim_host(func); | 977 | sdio_claim_host(func); |
1019 | 978 | ||
1020 | ret = sdio_enable_func(func); | 979 | ret = sdio_enable_func(func); |
@@ -1028,7 +987,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1028 | /* For 1-bit transfers to the 8686 model, we need to enable the | 987 | /* For 1-bit transfers to the 8686 model, we need to enable the |
1029 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | 988 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 |
1030 | * bit to allow access to non-vendor registers. */ | 989 | * bit to allow access to non-vendor registers. */ |
1031 | if ((card->model == IF_SDIO_MODEL_8686) && | 990 | if ((card->model == MODEL_8686) && |
1032 | (host->caps & MMC_CAP_SDIO_IRQ) && | 991 | (host->caps & MMC_CAP_SDIO_IRQ) && |
1033 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | 992 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { |
1034 | u8 reg; | 993 | u8 reg; |
@@ -1091,8 +1050,8 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1091 | * Get rx_unit if the chip is SD8688 or newer. | 1050 | * Get rx_unit if the chip is SD8688 or newer. |
1092 | * SD8385 & SD8686 do not have rx_unit. | 1051 | * SD8385 & SD8686 do not have rx_unit. |
1093 | */ | 1052 | */ |
1094 | if ((card->model != IF_SDIO_MODEL_8385) | 1053 | if ((card->model != MODEL_8385) |
1095 | && (card->model != IF_SDIO_MODEL_8686)) | 1054 | && (card->model != MODEL_8686)) |
1096 | card->rx_unit = if_sdio_read_rx_unit(card); | 1055 | card->rx_unit = if_sdio_read_rx_unit(card); |
1097 | else | 1056 | else |
1098 | card->rx_unit = 0; | 1057 | card->rx_unit = 0; |
@@ -1108,7 +1067,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1108 | /* | 1067 | /* |
1109 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 1068 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
1110 | */ | 1069 | */ |
1111 | if (card->model == IF_SDIO_MODEL_8688) { | 1070 | if (card->model == MODEL_8688) { |
1112 | struct cmd_header cmd; | 1071 | struct cmd_header cmd; |
1113 | 1072 | ||
1114 | memset(&cmd, 0, sizeof(cmd)); | 1073 | memset(&cmd, 0, sizeof(cmd)); |
@@ -1165,7 +1124,7 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1165 | 1124 | ||
1166 | card = sdio_get_drvdata(func); | 1125 | card = sdio_get_drvdata(func); |
1167 | 1126 | ||
1168 | if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { | 1127 | if (user_rmmod && (card->model == MODEL_8688)) { |
1169 | /* | 1128 | /* |
1170 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT | 1129 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT |
1171 | * multiple functions | 1130 | * multiple functions |
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 12179c1dc9c9..62fda3592f67 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -12,10 +12,6 @@ | |||
12 | #ifndef _LBS_IF_SDIO_H | 12 | #ifndef _LBS_IF_SDIO_H |
13 | #define _LBS_IF_SDIO_H | 13 | #define _LBS_IF_SDIO_H |
14 | 14 | ||
15 | #define IF_SDIO_MODEL_8385 0x04 | ||
16 | #define IF_SDIO_MODEL_8686 0x0b | ||
17 | #define IF_SDIO_MODEL_8688 0x10 | ||
18 | |||
19 | #define IF_SDIO_IOPORT 0x00 | 15 | #define IF_SDIO_IOPORT 0x00 |
20 | 16 | ||
21 | #define IF_SDIO_H_INT_MASK 0x04 | 17 | #define IF_SDIO_H_INT_MASK 0x04 |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index fe3f08028eb3..79bcb4e5d2ca 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -39,9 +39,6 @@ struct if_spi_card { | |||
39 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
40 | struct libertas_spi_platform_data *pdata; | 40 | struct libertas_spi_platform_data *pdata; |
41 | 41 | ||
42 | char helper_fw_name[IF_SPI_FW_NAME_MAX]; | ||
43 | char main_fw_name[IF_SPI_FW_NAME_MAX]; | ||
44 | |||
45 | /* The card ID and card revision, as reported by the hardware. */ | 42 | /* The card ID and card revision, as reported by the hardware. */ |
46 | u16 card_id; | 43 | u16 card_id; |
47 | u8 card_rev; | 44 | u8 card_rev; |
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card) | |||
70 | kfree(card); | 67 | kfree(card); |
71 | } | 68 | } |
72 | 69 | ||
73 | static struct chip_ident chip_id_to_device_name[] = { | 70 | #define MODEL_8385 0x04 |
74 | { .chip_id = 0x04, .name = 8385 }, | 71 | #define MODEL_8686 0x0b |
75 | { .chip_id = 0x0b, .name = 8686 }, | 72 | #define MODEL_8688 0x10 |
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" }, | ||
76 | { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" }, | ||
77 | { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" }, | ||
78 | { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" }, | ||
79 | { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" }, | ||
80 | { 0, NULL, NULL } | ||
76 | }; | 81 | }; |
82 | MODULE_FIRMWARE("libertas/gspi8385_helper.bin"); | ||
83 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
84 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
85 | MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin"); | ||
86 | MODULE_FIRMWARE("libertas/gspi8686_v9.bin"); | ||
87 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
88 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
89 | MODULE_FIRMWARE("libertas/gspi8688_helper.bin"); | ||
90 | MODULE_FIRMWARE("libertas/gspi8688.bin"); | ||
91 | |||
77 | 92 | ||
78 | /* | 93 | /* |
79 | * SPI Interface Unit Routines | 94 | * SPI Interface Unit Routines |
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) | |||
399 | * Firmware Loading | 414 | * Firmware Loading |
400 | */ | 415 | */ |
401 | 416 | ||
402 | static int if_spi_prog_helper_firmware(struct if_spi_card *card) | 417 | static int if_spi_prog_helper_firmware(struct if_spi_card *card, |
418 | const struct firmware *firmware) | ||
403 | { | 419 | { |
404 | int err = 0; | 420 | int err = 0; |
405 | const struct firmware *firmware = NULL; | ||
406 | int bytes_remaining; | 421 | int bytes_remaining; |
407 | const u8 *fw; | 422 | const u8 *fw; |
408 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; | 423 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; |
409 | struct spi_device *spi = card->spi; | ||
410 | 424 | ||
411 | lbs_deb_enter(LBS_DEB_SPI); | 425 | lbs_deb_enter(LBS_DEB_SPI); |
412 | 426 | ||
413 | err = spu_set_interrupt_mode(card, 1, 0); | 427 | err = spu_set_interrupt_mode(card, 1, 0); |
414 | if (err) | 428 | if (err) |
415 | goto out; | 429 | goto out; |
416 | /* Get helper firmware image */ | 430 | |
417 | err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); | ||
418 | if (err) { | ||
419 | lbs_pr_err("request_firmware failed with err = %d\n", err); | ||
420 | goto out; | ||
421 | } | ||
422 | bytes_remaining = firmware->size; | 431 | bytes_remaining = firmware->size; |
423 | fw = firmware->data; | 432 | fw = firmware->data; |
424 | 433 | ||
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
429 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, | 438 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, |
430 | HELPER_FW_LOAD_CHUNK_SZ); | 439 | HELPER_FW_LOAD_CHUNK_SZ); |
431 | if (err) | 440 | if (err) |
432 | goto release_firmware; | 441 | goto out; |
433 | 442 | ||
434 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 443 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
435 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | 444 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, |
436 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | 445 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); |
437 | if (err) | 446 | if (err) |
438 | goto release_firmware; | 447 | goto out; |
439 | 448 | ||
440 | /* Feed the data into the command read/write port reg | 449 | /* Feed the data into the command read/write port reg |
441 | * in chunks of 64 bytes */ | 450 | * in chunks of 64 bytes */ |
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
446 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 455 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
447 | temp, HELPER_FW_LOAD_CHUNK_SZ); | 456 | temp, HELPER_FW_LOAD_CHUNK_SZ); |
448 | if (err) | 457 | if (err) |
449 | goto release_firmware; | 458 | goto out; |
450 | 459 | ||
451 | /* Interrupt the boot code */ | 460 | /* Interrupt the boot code */ |
452 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 461 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
453 | if (err) | 462 | if (err) |
454 | goto release_firmware; | 463 | goto out; |
455 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 464 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
456 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 465 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
457 | if (err) | 466 | if (err) |
458 | goto release_firmware; | 467 | goto out; |
459 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; | 468 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; |
460 | fw += HELPER_FW_LOAD_CHUNK_SZ; | 469 | fw += HELPER_FW_LOAD_CHUNK_SZ; |
461 | } | 470 | } |
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
465 | * bootloader. This completes the helper download. */ | 474 | * bootloader. This completes the helper download. */ |
466 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); | 475 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); |
467 | if (err) | 476 | if (err) |
468 | goto release_firmware; | 477 | goto out; |
469 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 478 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
470 | if (err) | 479 | if (err) |
471 | goto release_firmware; | 480 | goto out; |
472 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 481 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
473 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 482 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
474 | goto release_firmware; | 483 | goto out; |
475 | 484 | ||
476 | lbs_deb_spi("waiting for helper to boot...\n"); | 485 | lbs_deb_spi("waiting for helper to boot...\n"); |
477 | 486 | ||
478 | release_firmware: | ||
479 | release_firmware(firmware); | ||
480 | out: | 487 | out: |
481 | if (err) | 488 | if (err) |
482 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | 489 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); |
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
523 | return len; | 530 | return len; |
524 | } | 531 | } |
525 | 532 | ||
526 | static int if_spi_prog_main_firmware(struct if_spi_card *card) | 533 | static int if_spi_prog_main_firmware(struct if_spi_card *card, |
534 | const struct firmware *firmware) | ||
527 | { | 535 | { |
528 | int len, prev_len; | 536 | int len, prev_len; |
529 | int bytes, crc_err = 0, err = 0; | 537 | int bytes, crc_err = 0, err = 0; |
530 | const struct firmware *firmware = NULL; | ||
531 | const u8 *fw; | 538 | const u8 *fw; |
532 | struct spi_device *spi = card->spi; | ||
533 | u16 num_crc_errs; | 539 | u16 num_crc_errs; |
534 | 540 | ||
535 | lbs_deb_enter(LBS_DEB_SPI); | 541 | lbs_deb_enter(LBS_DEB_SPI); |
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
538 | if (err) | 544 | if (err) |
539 | goto out; | 545 | goto out; |
540 | 546 | ||
541 | /* Get firmware image */ | ||
542 | err = request_firmware(&firmware, card->main_fw_name, &spi->dev); | ||
543 | if (err) { | ||
544 | lbs_pr_err("%s: can't get firmware '%s' from kernel. " | ||
545 | "err = %d\n", __func__, card->main_fw_name, err); | ||
546 | goto out; | ||
547 | } | ||
548 | |||
549 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | 547 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); |
550 | if (err) { | 548 | if (err) { |
551 | lbs_pr_err("%s: timed out waiting for initial " | 549 | lbs_pr_err("%s: timed out waiting for initial " |
552 | "scratch reg = 0\n", __func__); | 550 | "scratch reg = 0\n", __func__); |
553 | goto release_firmware; | 551 | goto out; |
554 | } | 552 | } |
555 | 553 | ||
556 | num_crc_errs = 0; | 554 | num_crc_errs = 0; |
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
560 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { | 558 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { |
561 | if (len < 0) { | 559 | if (len < 0) { |
562 | err = len; | 560 | err = len; |
563 | goto release_firmware; | 561 | goto out; |
564 | } | 562 | } |
565 | if (bytes < 0) { | 563 | if (bytes < 0) { |
566 | /* If there are no more bytes left, we would normally | 564 | /* If there are no more bytes left, we would normally |
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
575 | lbs_pr_err("Too many CRC errors encountered " | 573 | lbs_pr_err("Too many CRC errors encountered " |
576 | "in firmware load.\n"); | 574 | "in firmware load.\n"); |
577 | err = -EIO; | 575 | err = -EIO; |
578 | goto release_firmware; | 576 | goto out; |
579 | } | 577 | } |
580 | } else { | 578 | } else { |
581 | /* Previous transfer succeeded. Advance counters. */ | 579 | /* Previous transfer succeeded. Advance counters. */ |
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
590 | 588 | ||
591 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 589 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
592 | if (err) | 590 | if (err) |
593 | goto release_firmware; | 591 | goto out; |
594 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 592 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
595 | card->cmd_buffer, len); | 593 | card->cmd_buffer, len); |
596 | if (err) | 594 | if (err) |
597 | goto release_firmware; | 595 | goto out; |
598 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , | 596 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , |
599 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 597 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
600 | if (err) | 598 | if (err) |
601 | goto release_firmware; | 599 | goto out; |
602 | prev_len = len; | 600 | prev_len = len; |
603 | } | 601 | } |
604 | if (bytes > prev_len) { | 602 | if (bytes > prev_len) { |
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
611 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | 609 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); |
612 | if (err) { | 610 | if (err) { |
613 | lbs_pr_err("failed to confirm the firmware download\n"); | 611 | lbs_pr_err("failed to confirm the firmware download\n"); |
614 | goto release_firmware; | 612 | goto out; |
615 | } | 613 | } |
616 | 614 | ||
617 | release_firmware: | ||
618 | release_firmware(firmware); | ||
619 | |||
620 | out: | 615 | out: |
621 | if (err) | 616 | if (err) |
622 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | 617 | lbs_pr_err("failed to load firmware (err=%d)\n", err); |
@@ -800,14 +795,16 @@ static int lbs_spi_thread(void *data) | |||
800 | goto err; | 795 | goto err; |
801 | } | 796 | } |
802 | 797 | ||
803 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) | 798 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { |
804 | err = if_spi_c2h_cmd(card); | 799 | err = if_spi_c2h_cmd(card); |
805 | if (err) | 800 | if (err) |
806 | goto err; | 801 | goto err; |
807 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) | 802 | } |
803 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | ||
808 | err = if_spi_c2h_data(card); | 804 | err = if_spi_c2h_data(card); |
809 | if (err) | 805 | if (err) |
810 | goto err; | 806 | goto err; |
807 | } | ||
811 | 808 | ||
812 | /* workaround: in PS mode, the card does not set the Command | 809 | /* workaround: in PS mode, the card does not set the Command |
813 | * Download Ready bit, but it sets TX Download Ready. */ | 810 | * Download Ready bit, but it sets TX Download Ready. */ |
@@ -886,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
886 | * SPI callbacks | 883 | * SPI callbacks |
887 | */ | 884 | */ |
888 | 885 | ||
889 | static int if_spi_calculate_fw_names(u16 card_id, | ||
890 | char *helper_fw, char *main_fw) | ||
891 | { | ||
892 | int i; | ||
893 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
894 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
895 | break; | ||
896 | } | ||
897 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
898 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
899 | return -EAFNOSUPPORT; | ||
900 | } | ||
901 | snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
902 | chip_id_to_device_name[i].name); | ||
903 | snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", | ||
904 | chip_id_to_device_name[i].name); | ||
905 | return 0; | ||
906 | } | ||
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
911 | |||
912 | static int __devinit if_spi_probe(struct spi_device *spi) | 886 | static int __devinit if_spi_probe(struct spi_device *spi) |
913 | { | 887 | { |
914 | struct if_spi_card *card; | 888 | struct if_spi_card *card; |
915 | struct lbs_private *priv = NULL; | 889 | struct lbs_private *priv = NULL; |
916 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; |
917 | int err = 0; | 891 | int err = 0, i; |
918 | u32 scratch; | 892 | u32 scratch; |
919 | struct sched_param param = { .sched_priority = 1 }; | 893 | struct sched_param param = { .sched_priority = 1 }; |
894 | const struct firmware *helper = NULL; | ||
895 | const struct firmware *mainfw = NULL; | ||
920 | 896 | ||
921 | lbs_deb_enter(LBS_DEB_SPI); | 897 | lbs_deb_enter(LBS_DEB_SPI); |
922 | 898 | ||
@@ -961,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
961 | lbs_deb_spi("Firmware is already loaded for " | 937 | lbs_deb_spi("Firmware is already loaded for " |
962 | "Marvell WLAN 802.11 adapter\n"); | 938 | "Marvell WLAN 802.11 adapter\n"); |
963 | else { | 939 | else { |
964 | err = if_spi_calculate_fw_names(card->card_id, | 940 | /* Check if we support this card */ |
965 | card->helper_fw_name, card->main_fw_name); | 941 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
966 | if (err) | 942 | if (card->card_id == fw_table[i].model) |
943 | break; | ||
944 | } | ||
945 | if (i == ARRAY_SIZE(fw_table)) { | ||
946 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | ||
947 | card->card_id); | ||
948 | err = -ENODEV; | ||
967 | goto free_card; | 949 | goto free_card; |
950 | } | ||
951 | |||
952 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | ||
953 | card->card_id, &fw_table[0], &helper, | ||
954 | &mainfw); | ||
955 | if (err) { | ||
956 | lbs_pr_err("failed to find firmware (%d)\n", err); | ||
957 | goto free_card; | ||
958 | } | ||
968 | 959 | ||
969 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
970 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | 961 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " |
@@ -973,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
973 | card->card_id, card->card_rev, | 964 | card->card_id, card->card_rev, |
974 | spi->master->bus_num, spi->chip_select, | 965 | spi->master->bus_num, spi->chip_select, |
975 | spi->max_speed_hz); | 966 | spi->max_speed_hz); |
976 | err = if_spi_prog_helper_firmware(card); | 967 | err = if_spi_prog_helper_firmware(card, helper); |
977 | if (err) | 968 | if (err) |
978 | goto free_card; | 969 | goto free_card; |
979 | err = if_spi_prog_main_firmware(card); | 970 | err = if_spi_prog_main_firmware(card, mainfw); |
980 | if (err) | 971 | if (err) |
981 | goto free_card; | 972 | goto free_card; |
982 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | 973 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); |
@@ -1044,6 +1035,11 @@ remove_card: | |||
1044 | free_card: | 1035 | free_card: |
1045 | free_if_spi_card(card); | 1036 | free_if_spi_card(card); |
1046 | out: | 1037 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1047 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1048 | return err; | 1044 | return err; |
1049 | } | 1045 | } |
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index f87eec410848..8b1417d3b71b 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h | |||
@@ -25,11 +25,6 @@ | |||
25 | 25 | ||
26 | #define IF_SPI_FW_NAME_MAX 30 | 26 | #define IF_SPI_FW_NAME_MAX 30 |
27 | 27 | ||
28 | struct chip_ident { | ||
29 | u16 chip_id; | ||
30 | u16 name; | ||
31 | }; | ||
32 | |||
33 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 | 28 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 |
34 | 29 | ||
35 | /* Chunk size when loading the helper firmware */ | 30 | /* Chunk size when loading the helper firmware */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 3ff61063671a..e906616232a2 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -26,15 +26,25 @@ | |||
26 | 26 | ||
27 | #define MESSAGE_HEADER_LEN 4 | 27 | #define MESSAGE_HEADER_LEN 4 |
28 | 28 | ||
29 | static char *lbs_fw_name = "usb8388.bin"; | 29 | static char *lbs_fw_name = NULL; |
30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | 30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); |
31 | 31 | ||
32 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); | ||
33 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); | ||
34 | MODULE_FIRMWARE("libertas/usb8388.bin"); | ||
35 | MODULE_FIRMWARE("libertas/usb8682.bin"); | ||
32 | MODULE_FIRMWARE("usb8388.bin"); | 36 | MODULE_FIRMWARE("usb8388.bin"); |
33 | 37 | ||
38 | enum { | ||
39 | MODEL_UNKNOWN = 0x0, | ||
40 | MODEL_8388 = 0x1, | ||
41 | MODEL_8682 = 0x2 | ||
42 | }; | ||
43 | |||
34 | static struct usb_device_id if_usb_table[] = { | 44 | static struct usb_device_id if_usb_table[] = { |
35 | /* Enter the device signature inside */ | 45 | /* Enter the device signature inside */ |
36 | { USB_DEVICE(0x1286, 0x2001) }, | 46 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, |
37 | { USB_DEVICE(0x05a3, 0x8388) }, | 47 | { USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 }, |
38 | {} /* Terminating entry */ | 48 | {} /* Terminating entry */ |
39 | }; | 49 | }; |
40 | 50 | ||
@@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev, | |||
66 | struct if_usb_card *cardp = priv->card; | 76 | struct if_usb_card *cardp = priv->card; |
67 | int ret; | 77 | int ret; |
68 | 78 | ||
79 | BUG_ON(buf == NULL); | ||
80 | |||
69 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); | 81 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); |
70 | if (ret == 0) | 82 | if (ret == 0) |
71 | return count; | 83 | return count; |
@@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev, | |||
91 | struct if_usb_card *cardp = priv->card; | 103 | struct if_usb_card *cardp = priv->card; |
92 | int ret; | 104 | int ret; |
93 | 105 | ||
106 | BUG_ON(buf == NULL); | ||
107 | |||
94 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); | 108 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); |
95 | if (ret == 0) | 109 | if (ret == 0) |
96 | return count; | 110 | return count; |
@@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf, | |||
244 | init_waitqueue_head(&cardp->fw_wq); | 258 | init_waitqueue_head(&cardp->fw_wq); |
245 | 259 | ||
246 | cardp->udev = udev; | 260 | cardp->udev = udev; |
261 | cardp->model = (uint32_t) id->driver_info; | ||
247 | iface_desc = intf->cur_altsetting; | 262 | iface_desc = intf->cur_altsetting; |
248 | 263 | ||
249 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" | 264 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" |
@@ -924,6 +939,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp, | |||
924 | return ret; | 939 | return ret; |
925 | } | 940 | } |
926 | 941 | ||
942 | /* table of firmware file names */ | ||
943 | static const struct { | ||
944 | u32 model; | ||
945 | const char *fwname; | ||
946 | } fw_table[] = { | ||
947 | { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
948 | { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
949 | { MODEL_8388, "libertas/usb8388.bin" }, | ||
950 | { MODEL_8388, "usb8388.bin" }, | ||
951 | { MODEL_8682, "libertas/usb8682.bin" } | ||
952 | }; | ||
953 | |||
954 | static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
955 | { | ||
956 | int i; | ||
957 | |||
958 | /* Try user-specified firmware first */ | ||
959 | if (fwname) | ||
960 | return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | ||
961 | |||
962 | /* Otherwise search for firmware to use */ | ||
963 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
964 | if (fw_table[i].model != cardp->model) | ||
965 | continue; | ||
966 | if (request_firmware(&cardp->fw, fw_table[i].fwname, | ||
967 | &cardp->udev->dev) == 0) | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | return -ENOENT; | ||
972 | } | ||
973 | |||
927 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, | 974 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, |
928 | const char *fwname, int cmd) | 975 | const char *fwname, int cmd) |
929 | { | 976 | { |
@@ -933,10 +980,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, | |||
933 | 980 | ||
934 | lbs_deb_enter(LBS_DEB_USB); | 981 | lbs_deb_enter(LBS_DEB_USB); |
935 | 982 | ||
936 | ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | 983 | ret = get_fw(cardp, fwname); |
937 | if (ret < 0) { | 984 | if (ret) { |
938 | lbs_pr_err("request_firmware() failed with %#x\n", ret); | 985 | lbs_pr_err("failed to find firmware (%d)\n", ret); |
939 | lbs_pr_err("firmware %s not found\n", fwname); | ||
940 | goto done; | 986 | goto done; |
941 | } | 987 | } |
942 | 988 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 5ba0aee0eb2f..d819e7e3c9aa 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -43,6 +43,7 @@ struct bootcmdresp | |||
43 | /** USB card description structure*/ | 43 | /** USB card description structure*/ |
44 | struct if_usb_card { | 44 | struct if_usb_card { |
45 | struct usb_device *udev; | 45 | struct usb_device *udev; |
46 | uint32_t model; /* MODEL_* */ | ||
46 | struct urb *rx_urb, *tx_urb; | 47 | struct urb *rx_urb, *tx_urb; |
47 | struct lbs_private *priv; | 48 | struct lbs_private *priv; |
48 | 49 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 24958a86747b..47ce5a6ba120 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | |||
1047 | } | 1047 | } |
1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); | 1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1049 | 1049 | ||
1050 | /** | ||
1051 | * @brief Retrieves two-stage firmware | ||
1052 | * | ||
1053 | * @param dev A pointer to device structure | ||
1054 | * @param user_helper User-defined helper firmware file | ||
1055 | * @param user_mainfw User-defined main firmware file | ||
1056 | * @param card_model Bus-specific card model ID used to filter firmware table | ||
1057 | * elements | ||
1058 | * @param fw_table Table of firmware file names and device model numbers | ||
1059 | * terminated by an entry with a NULL helper name | ||
1060 | * @param helper On success, the helper firmware; caller must free | ||
1061 | * @param mainfw On success, the main firmware; caller must free | ||
1062 | * | ||
1063 | * @return 0 on success, non-zero on failure | ||
1064 | */ | ||
1065 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
1066 | const char *user_mainfw, u32 card_model, | ||
1067 | const struct lbs_fw_table *fw_table, | ||
1068 | const struct firmware **helper, | ||
1069 | const struct firmware **mainfw) | ||
1070 | { | ||
1071 | const struct lbs_fw_table *iter; | ||
1072 | int ret; | ||
1073 | |||
1074 | BUG_ON(helper == NULL); | ||
1075 | BUG_ON(mainfw == NULL); | ||
1076 | |||
1077 | /* Try user-specified firmware first */ | ||
1078 | if (user_helper) { | ||
1079 | ret = request_firmware(helper, user_helper, dev); | ||
1080 | if (ret) { | ||
1081 | lbs_pr_err("couldn't find helper firmware %s", | ||
1082 | user_helper); | ||
1083 | goto fail; | ||
1084 | } | ||
1085 | } | ||
1086 | if (user_mainfw) { | ||
1087 | ret = request_firmware(mainfw, user_mainfw, dev); | ||
1088 | if (ret) { | ||
1089 | lbs_pr_err("couldn't find main firmware %s", | ||
1090 | user_mainfw); | ||
1091 | goto fail; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | if (*helper && *mainfw) | ||
1096 | return 0; | ||
1097 | |||
1098 | /* Otherwise search for firmware to use. If neither the helper or | ||
1099 | * the main firmware were specified by the user, then we need to | ||
1100 | * make sure that found helper & main are from the same entry in | ||
1101 | * fw_table. | ||
1102 | */ | ||
1103 | iter = fw_table; | ||
1104 | while (iter && iter->helper) { | ||
1105 | if (iter->model != card_model) | ||
1106 | goto next; | ||
1107 | |||
1108 | if (*helper == NULL) { | ||
1109 | ret = request_firmware(helper, iter->helper, dev); | ||
1110 | if (ret) | ||
1111 | goto next; | ||
1112 | |||
1113 | /* If the device has one-stage firmware (ie cf8305) and | ||
1114 | * we've got it then we don't need to bother with the | ||
1115 | * main firmware. | ||
1116 | */ | ||
1117 | if (iter->fwname == NULL) | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | if (*mainfw == NULL) { | ||
1122 | ret = request_firmware(mainfw, iter->fwname, dev); | ||
1123 | if (ret && !user_helper) { | ||
1124 | /* Clear the helper if it wasn't user-specified | ||
1125 | * and the main firmware load failed, to ensure | ||
1126 | * we don't have mismatched firmware pairs. | ||
1127 | */ | ||
1128 | release_firmware(*helper); | ||
1129 | *helper = NULL; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | if (*helper && *mainfw) | ||
1134 | return 0; | ||
1135 | |||
1136 | next: | ||
1137 | iter++; | ||
1138 | } | ||
1139 | |||
1140 | fail: | ||
1141 | /* Failed */ | ||
1142 | if (*helper) { | ||
1143 | release_firmware(*helper); | ||
1144 | *helper = NULL; | ||
1145 | } | ||
1146 | if (*mainfw) { | ||
1147 | release_firmware(*mainfw); | ||
1148 | *mainfw = NULL; | ||
1149 | } | ||
1150 | |||
1151 | return -ENOENT; | ||
1152 | } | ||
1153 | EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
1154 | |||
1050 | static int __init lbs_init_module(void) | 1155 | static int __init lbs_init_module(void) |
1051 | { | 1156 | { |
1052 | lbs_deb_enter(LBS_DEB_MAIN); | 1157 | lbs_deb_enter(LBS_DEB_MAIN); |