diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_sdio.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e998c123e0c..478d766abf8 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -61,6 +61,7 @@ struct if_sdio_model { | |||
61 | int model; | 61 | int model; |
62 | const char *helper; | 62 | const char *helper; |
63 | const char *firmware; | 63 | const char *firmware; |
64 | struct if_sdio_card *card; | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static struct if_sdio_model if_sdio_models[] = { | 67 | static struct if_sdio_model if_sdio_models[] = { |
@@ -69,18 +70,21 @@ static struct if_sdio_model if_sdio_models[] = { | |||
69 | .model = IF_SDIO_MODEL_8385, | 70 | .model = IF_SDIO_MODEL_8385, |
70 | .helper = "sd8385_helper.bin", | 71 | .helper = "sd8385_helper.bin", |
71 | .firmware = "sd8385.bin", | 72 | .firmware = "sd8385.bin", |
73 | .card = NULL, | ||
72 | }, | 74 | }, |
73 | { | 75 | { |
74 | /* 8686 */ | 76 | /* 8686 */ |
75 | .model = IF_SDIO_MODEL_8686, | 77 | .model = IF_SDIO_MODEL_8686, |
76 | .helper = "sd8686_helper.bin", | 78 | .helper = "sd8686_helper.bin", |
77 | .firmware = "sd8686.bin", | 79 | .firmware = "sd8686.bin", |
80 | .card = NULL, | ||
78 | }, | 81 | }, |
79 | { | 82 | { |
80 | /* 8688 */ | 83 | /* 8688 */ |
81 | .model = IF_SDIO_MODEL_8688, | 84 | .model = IF_SDIO_MODEL_8688, |
82 | .helper = "sd8688_helper.bin", | 85 | .helper = "sd8688_helper.bin", |
83 | .firmware = "sd8688.bin", | 86 | .firmware = "sd8688.bin", |
87 | .card = NULL, | ||
84 | }, | 88 | }, |
85 | }; | 89 | }; |
86 | 90 | ||
@@ -539,7 +543,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
539 | ret = 0; | 543 | ret = 0; |
540 | 544 | ||
541 | release: | 545 | release: |
542 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
543 | sdio_release_host(card->func); | 546 | sdio_release_host(card->func); |
544 | kfree(chunk_buffer); | 547 | kfree(chunk_buffer); |
545 | release_fw: | 548 | release_fw: |
@@ -675,7 +678,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
675 | ret = 0; | 678 | ret = 0; |
676 | 679 | ||
677 | release: | 680 | release: |
678 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
679 | sdio_release_host(card->func); | 681 | sdio_release_host(card->func); |
680 | kfree(chunk_buffer); | 682 | kfree(chunk_buffer); |
681 | release_fw: | 683 | release_fw: |
@@ -718,6 +720,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
718 | goto out; | 720 | goto out; |
719 | 721 | ||
720 | success: | 722 | success: |
723 | sdio_claim_host(card->func); | ||
724 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
725 | sdio_release_host(card->func); | ||
721 | ret = 0; | 726 | ret = 0; |
722 | 727 | ||
723 | out: | 728 | out: |
@@ -903,6 +908,8 @@ static int if_sdio_probe(struct sdio_func *func, | |||
903 | goto free; | 908 | goto free; |
904 | } | 909 | } |
905 | 910 | ||
911 | if_sdio_models[i].card = card; | ||
912 | |||
906 | card->helper = if_sdio_models[i].helper; | 913 | card->helper = if_sdio_models[i].helper; |
907 | card->firmware = if_sdio_models[i].firmware; | 914 | card->firmware = if_sdio_models[i].firmware; |
908 | 915 | ||
@@ -985,6 +992,12 @@ static int if_sdio_probe(struct sdio_func *func, | |||
985 | if (ret) | 992 | if (ret) |
986 | goto reclaim; | 993 | goto reclaim; |
987 | 994 | ||
995 | /* | ||
996 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | ||
997 | */ | ||
998 | priv->fn_init_required = | ||
999 | (card->model == IF_SDIO_MODEL_8688) ? 1 : 0; | ||
1000 | |||
988 | ret = lbs_start_card(priv); | 1001 | ret = lbs_start_card(priv); |
989 | if (ret) | 1002 | if (ret) |
990 | goto err_activate_card; | 1003 | goto err_activate_card; |
@@ -1025,23 +1038,30 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1025 | { | 1038 | { |
1026 | struct if_sdio_card *card; | 1039 | struct if_sdio_card *card; |
1027 | struct if_sdio_packet *packet; | 1040 | struct if_sdio_packet *packet; |
1041 | int ret; | ||
1028 | 1042 | ||
1029 | lbs_deb_enter(LBS_DEB_SDIO); | 1043 | lbs_deb_enter(LBS_DEB_SDIO); |
1030 | 1044 | ||
1031 | card = sdio_get_drvdata(func); | 1045 | card = sdio_get_drvdata(func); |
1032 | 1046 | ||
1047 | lbs_stop_card(card->priv); | ||
1048 | |||
1033 | card->priv->surpriseremoved = 1; | 1049 | card->priv->surpriseremoved = 1; |
1034 | 1050 | ||
1035 | lbs_deb_sdio("call remove card\n"); | 1051 | lbs_deb_sdio("call remove card\n"); |
1036 | lbs_stop_card(card->priv); | ||
1037 | lbs_remove_card(card->priv); | 1052 | lbs_remove_card(card->priv); |
1038 | 1053 | ||
1039 | flush_workqueue(card->workqueue); | 1054 | flush_workqueue(card->workqueue); |
1040 | destroy_workqueue(card->workqueue); | 1055 | destroy_workqueue(card->workqueue); |
1041 | 1056 | ||
1042 | sdio_claim_host(func); | 1057 | sdio_claim_host(func); |
1058 | |||
1059 | /* Disable interrupts */ | ||
1060 | sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret); | ||
1061 | |||
1043 | sdio_release_irq(func); | 1062 | sdio_release_irq(func); |
1044 | sdio_disable_func(func); | 1063 | sdio_disable_func(func); |
1064 | |||
1045 | sdio_release_host(func); | 1065 | sdio_release_host(func); |
1046 | 1066 | ||
1047 | while (card->packets) { | 1067 | while (card->packets) { |
@@ -1084,8 +1104,23 @@ static int __init if_sdio_init_module(void) | |||
1084 | 1104 | ||
1085 | static void __exit if_sdio_exit_module(void) | 1105 | static void __exit if_sdio_exit_module(void) |
1086 | { | 1106 | { |
1107 | int i; | ||
1108 | struct if_sdio_card *card; | ||
1109 | |||
1087 | lbs_deb_enter(LBS_DEB_SDIO); | 1110 | lbs_deb_enter(LBS_DEB_SDIO); |
1088 | 1111 | ||
1112 | for (i = 0; i < ARRAY_SIZE(if_sdio_models); i++) { | ||
1113 | card = if_sdio_models[i].card; | ||
1114 | |||
1115 | /* | ||
1116 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT | ||
1117 | * multiple functions | ||
1118 | */ | ||
1119 | if (card && card->priv) | ||
1120 | card->priv->fn_shutdown_required = | ||
1121 | (card->model == IF_SDIO_MODEL_8688) ? 1 : 0; | ||
1122 | } | ||
1123 | |||
1089 | sdio_unregister_driver(&if_sdio_driver); | 1124 | sdio_unregister_driver(&if_sdio_driver); |
1090 | 1125 | ||
1091 | lbs_deb_leave(LBS_DEB_SDIO); | 1126 | lbs_deb_leave(LBS_DEB_SDIO); |