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/if_sdio.c | |
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/if_sdio.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 161 |
1 files changed, 60 insertions, 101 deletions
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 |