diff options
author | Dan Williams <dcbw@redhat.com> | 2010-08-07 22:15:19 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-16 15:26:43 -0400 |
commit | 82222e9ba75298e5bcd89803b6a11e2d7dfae70e (patch) | |
tree | 5594a7c0ffa78489beff83fa98b9adeb269cee05 | |
parent | 72f7a6671e8a1433467757e94c883d39eeccd4ba (diff) |
libertas: [cs] use common firmware request helper and new firmware locations
linux-firmware puts libertas firmware in /libertas. Fix the driver to
look there first, but fall back to the old firmware names if the new
ones don't exist.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 130 |
1 files changed, 74 insertions, 56 deletions
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 08e4e390800..a6fd70404c3 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -49,7 +49,6 @@ | |||
49 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); | 49 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); |
50 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); | 50 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); |
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
53 | 52 | ||
54 | 53 | ||
55 | 54 | ||
@@ -62,9 +61,34 @@ struct if_cs_card { | |||
62 | struct lbs_private *priv; | 61 | struct lbs_private *priv; |
63 | void __iomem *iobase; | 62 | void __iomem *iobase; |
64 | bool align_regs; | 63 | bool align_regs; |
64 | u32 model; | ||
65 | }; | 65 | }; |
66 | 66 | ||
67 | 67 | ||
68 | enum { | ||
69 | MODEL_UNKNOWN = 0x00, | ||
70 | MODEL_8305 = 0x01, | ||
71 | MODEL_8381 = 0x02, | ||
72 | MODEL_8385 = 0x03 | ||
73 | }; | ||
74 | |||
75 | static const struct lbs_fw_table fw_table[] = { | ||
76 | { MODEL_8305, "libertas/cf8305.bin", NULL }, | ||
77 | { MODEL_8305, "libertas_cs_helper.fw", NULL }, | ||
78 | { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" }, | ||
79 | { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
80 | { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" }, | ||
81 | { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
82 | { 0, NULL, NULL } | ||
83 | }; | ||
84 | MODULE_FIRMWARE("libertas/cf8305.bin"); | ||
85 | MODULE_FIRMWARE("libertas/cf8381_helper.bin"); | ||
86 | MODULE_FIRMWARE("libertas/cf8381.bin"); | ||
87 | MODULE_FIRMWARE("libertas/cf8385_helper.bin"); | ||
88 | MODULE_FIRMWARE("libertas/cf8385.bin"); | ||
89 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
90 | MODULE_FIRMWARE("libertas_cs.fw"); | ||
91 | |||
68 | 92 | ||
69 | /********************************************************************/ | 93 | /********************************************************************/ |
70 | /* Hardware access */ | 94 | /* Hardware access */ |
@@ -290,22 +314,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
290 | #define CF8385_MANFID 0x02df | 314 | #define CF8385_MANFID 0x02df |
291 | #define CF8385_CARDID 0x8103 | 315 | #define CF8385_CARDID 0x8103 |
292 | 316 | ||
293 | static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) | 317 | /* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when |
294 | { | 318 | * that gets fixed. Currently there's no way to access it from the probe hook. |
295 | return (p_dev->manf_id == CF8305_MANFID && | 319 | */ |
296 | p_dev->card_id == CF8305_CARDID); | 320 | static inline u32 get_model(u16 manf_id, u16 card_id) |
297 | } | ||
298 | |||
299 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) | ||
300 | { | ||
301 | return (p_dev->manf_id == CF8381_MANFID && | ||
302 | p_dev->card_id == CF8381_CARDID); | ||
303 | } | ||
304 | |||
305 | static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) | ||
306 | { | 321 | { |
307 | return (p_dev->manf_id == CF8385_MANFID && | 322 | /* NOTE: keep in sync with if_cs_ids */ |
308 | p_dev->card_id == CF8385_CARDID); | 323 | if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID) |
324 | return MODEL_8305; | ||
325 | else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID) | ||
326 | return MODEL_8381; | ||
327 | else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID) | ||
328 | return MODEL_8385; | ||
329 | return MODEL_UNKNOWN; | ||
309 | } | 330 | } |
310 | 331 | ||
311 | /********************************************************************/ | 332 | /********************************************************************/ |
@@ -559,12 +580,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
559 | * | 580 | * |
560 | * Return 0 on success | 581 | * Return 0 on success |
561 | */ | 582 | */ |
562 | static int if_cs_prog_helper(struct if_cs_card *card) | 583 | static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) |
563 | { | 584 | { |
564 | int ret = 0; | 585 | int ret = 0; |
565 | int sent = 0; | 586 | int sent = 0; |
566 | u8 scratch; | 587 | u8 scratch; |
567 | const struct firmware *fw; | ||
568 | 588 | ||
569 | lbs_deb_enter(LBS_DEB_CS); | 589 | lbs_deb_enter(LBS_DEB_CS); |
570 | 590 | ||
@@ -590,14 +610,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
590 | goto done; | 610 | goto done; |
591 | } | 611 | } |
592 | 612 | ||
593 | /* TODO: make firmware file configurable */ | ||
594 | ret = request_firmware(&fw, "libertas_cs_helper.fw", | ||
595 | &card->p_dev->dev); | ||
596 | if (ret) { | ||
597 | lbs_pr_err("can't load helper firmware\n"); | ||
598 | ret = -ENODEV; | ||
599 | goto done; | ||
600 | } | ||
601 | lbs_deb_cs("helper size %td\n", fw->size); | 613 | lbs_deb_cs("helper size %td\n", fw->size); |
602 | 614 | ||
603 | /* "Set the 5 bytes of the helper image to 0" */ | 615 | /* "Set the 5 bytes of the helper image to 0" */ |
@@ -636,7 +648,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
636 | if (ret < 0) { | 648 | if (ret < 0) { |
637 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 649 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", |
638 | sent, ret); | 650 | sent, ret); |
639 | goto err_release; | 651 | goto done; |
640 | } | 652 | } |
641 | 653 | ||
642 | if (count == 0) | 654 | if (count == 0) |
@@ -645,17 +657,14 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
645 | sent += count; | 657 | sent += count; |
646 | } | 658 | } |
647 | 659 | ||
648 | err_release: | ||
649 | release_firmware(fw); | ||
650 | done: | 660 | done: |
651 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 661 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
652 | return ret; | 662 | return ret; |
653 | } | 663 | } |
654 | 664 | ||
655 | 665 | ||
656 | static int if_cs_prog_real(struct if_cs_card *card) | 666 | static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) |
657 | { | 667 | { |
658 | const struct firmware *fw; | ||
659 | int ret = 0; | 668 | int ret = 0; |
660 | int retry = 0; | 669 | int retry = 0; |
661 | int len = 0; | 670 | int len = 0; |
@@ -663,21 +672,13 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
663 | 672 | ||
664 | lbs_deb_enter(LBS_DEB_CS); | 673 | lbs_deb_enter(LBS_DEB_CS); |
665 | 674 | ||
666 | /* TODO: make firmware file configurable */ | ||
667 | ret = request_firmware(&fw, "libertas_cs.fw", | ||
668 | &card->p_dev->dev); | ||
669 | if (ret) { | ||
670 | lbs_pr_err("can't load firmware\n"); | ||
671 | ret = -ENODEV; | ||
672 | goto done; | ||
673 | } | ||
674 | lbs_deb_cs("fw size %td\n", fw->size); | 675 | lbs_deb_cs("fw size %td\n", fw->size); |
675 | 676 | ||
676 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, | 677 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, |
677 | IF_CS_SQ_HELPER_OK); | 678 | IF_CS_SQ_HELPER_OK); |
678 | if (ret < 0) { | 679 | if (ret < 0) { |
679 | lbs_pr_err("helper firmware doesn't answer\n"); | 680 | lbs_pr_err("helper firmware doesn't answer\n"); |
680 | goto err_release; | 681 | goto done; |
681 | } | 682 | } |
682 | 683 | ||
683 | for (sent = 0; sent < fw->size; sent += len) { | 684 | for (sent = 0; sent < fw->size; sent += len) { |
@@ -692,7 +693,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
692 | if (retry > 20) { | 693 | if (retry > 20) { |
693 | lbs_pr_err("could not download firmware\n"); | 694 | lbs_pr_err("could not download firmware\n"); |
694 | ret = -ENODEV; | 695 | ret = -ENODEV; |
695 | goto err_release; | 696 | goto done; |
696 | } | 697 | } |
697 | if (retry) { | 698 | if (retry) { |
698 | sent -= len; | 699 | sent -= len; |
@@ -711,7 +712,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
711 | IF_CS_BIT_COMMAND); | 712 | IF_CS_BIT_COMMAND); |
712 | if (ret < 0) { | 713 | if (ret < 0) { |
713 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 714 | lbs_pr_err("can't download firmware at 0x%x\n", sent); |
714 | goto err_release; | 715 | goto done; |
715 | } | 716 | } |
716 | } | 717 | } |
717 | 718 | ||
@@ -719,9 +720,6 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
719 | if (ret < 0) | 720 | if (ret < 0) |
720 | lbs_pr_err("firmware download failed\n"); | 721 | lbs_pr_err("firmware download failed\n"); |
721 | 722 | ||
722 | err_release: | ||
723 | release_firmware(fw); | ||
724 | |||
725 | done: | 723 | done: |
726 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 724 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
727 | return ret; | 725 | return ret; |
@@ -825,6 +823,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
825 | unsigned int prod_id; | 823 | unsigned int prod_id; |
826 | struct lbs_private *priv; | 824 | struct lbs_private *priv; |
827 | struct if_cs_card *card; | 825 | struct if_cs_card *card; |
826 | const struct firmware *helper = NULL; | ||
827 | const struct firmware *mainfw = NULL; | ||
828 | 828 | ||
829 | lbs_deb_enter(LBS_DEB_CS); | 829 | lbs_deb_enter(LBS_DEB_CS); |
830 | 830 | ||
@@ -844,7 +844,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
844 | goto out1; | 844 | goto out1; |
845 | } | 845 | } |
846 | 846 | ||
847 | |||
848 | /* | 847 | /* |
849 | * Allocate an interrupt line. Note that this does not assign | 848 | * Allocate an interrupt line. Note that this does not assign |
850 | * a handler to the interrupt, unless the 'Handler' member of | 849 | * a handler to the interrupt, unless the 'Handler' member of |
@@ -883,34 +882,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
883 | */ | 882 | */ |
884 | card->align_regs = 0; | 883 | card->align_regs = 0; |
885 | 884 | ||
885 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | ||
886 | if (card->model == MODEL_UNKNOWN) { | ||
887 | lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", | ||
888 | p_dev->manf_id, p_dev->card_id); | ||
889 | goto out2; | ||
890 | } | ||
891 | |||
886 | /* Check if we have a current silicon */ | 892 | /* Check if we have a current silicon */ |
887 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | 893 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); |
888 | if (if_cs_hw_is_cf8305(p_dev)) { | 894 | if (card->model == MODEL_8305) { |
889 | card->align_regs = 1; | 895 | card->align_regs = 1; |
890 | if (prod_id < IF_CS_CF8305_B1_REV) { | 896 | if (prod_id < IF_CS_CF8305_B1_REV) { |
891 | lbs_pr_err("old chips like 8305 rev B3 " | 897 | lbs_pr_err("8305 rev B0 and older are not supported\n"); |
892 | "aren't supported\n"); | ||
893 | ret = -ENODEV; | 898 | ret = -ENODEV; |
894 | goto out2; | 899 | goto out2; |
895 | } | 900 | } |
896 | } | 901 | } |
897 | 902 | ||
898 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { | 903 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { |
899 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); | 904 | lbs_pr_err("8381 rev B2 and older are not supported\n"); |
900 | ret = -ENODEV; | 905 | ret = -ENODEV; |
901 | goto out2; | 906 | goto out2; |
902 | } | 907 | } |
903 | 908 | ||
904 | if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { | 909 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { |
905 | lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); | 910 | lbs_pr_err("8385 rev B0 and older are not supported\n"); |
906 | ret = -ENODEV; | 911 | ret = -ENODEV; |
907 | goto out2; | 912 | goto out2; |
908 | } | 913 | } |
909 | 914 | ||
915 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | ||
916 | &fw_table[0], &helper, &mainfw); | ||
917 | if (ret) { | ||
918 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
919 | goto out2; | ||
920 | } | ||
921 | |||
910 | /* Load the firmware early, before calling into libertas.ko */ | 922 | /* Load the firmware early, before calling into libertas.ko */ |
911 | ret = if_cs_prog_helper(card); | 923 | ret = if_cs_prog_helper(card, helper); |
912 | if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) | 924 | if (ret == 0 && (card->model != MODEL_8305)) |
913 | ret = if_cs_prog_real(card); | 925 | ret = if_cs_prog_real(card, mainfw); |
914 | if (ret) | 926 | if (ret) |
915 | goto out2; | 927 | goto out2; |
916 | 928 | ||
@@ -959,6 +971,11 @@ out2: | |||
959 | out1: | 971 | out1: |
960 | pcmcia_disable_device(p_dev); | 972 | pcmcia_disable_device(p_dev); |
961 | out: | 973 | out: |
974 | if (helper) | ||
975 | release_firmware(helper); | ||
976 | if (mainfw) | ||
977 | release_firmware(mainfw); | ||
978 | |||
962 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 979 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
963 | return ret; | 980 | return ret; |
964 | } | 981 | } |
@@ -995,6 +1012,7 @@ static struct pcmcia_device_id if_cs_ids[] = { | |||
995 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), | 1012 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), |
996 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), | 1013 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), |
997 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), | 1014 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), |
1015 | /* NOTE: keep in sync with get_model() */ | ||
998 | PCMCIA_DEVICE_NULL, | 1016 | PCMCIA_DEVICE_NULL, |
999 | }; | 1017 | }; |
1000 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); | 1018 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); |