diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/host.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 20 |
4 files changed, 62 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index cbaafa653b6a..a4455ec7c354 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -321,6 +321,8 @@ struct lbs_private { | |||
321 | 321 | ||
322 | u32 monitormode; | 322 | u32 monitormode; |
323 | u8 fw_ready; | 323 | u8 fw_ready; |
324 | u8 fn_init_required; | ||
325 | u8 fn_shutdown_required; | ||
324 | }; | 326 | }; |
325 | 327 | ||
326 | extern struct cmd_confirm_sleep confirm_sleep; | 328 | extern struct cmd_confirm_sleep confirm_sleep; |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 8ff8ac9d817e..fe8f0cb737bc 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -86,6 +86,8 @@ | |||
86 | #define CMD_MESH_CONFIG_OLD 0x00a3 | 86 | #define CMD_MESH_CONFIG_OLD 0x00a3 |
87 | #define CMD_MESH_CONFIG 0x00ac | 87 | #define CMD_MESH_CONFIG 0x00ac |
88 | #define CMD_SET_BOOT2_VER 0x00a5 | 88 | #define CMD_SET_BOOT2_VER 0x00a5 |
89 | #define CMD_FUNC_INIT 0x00a9 | ||
90 | #define CMD_FUNC_SHUTDOWN 0x00aa | ||
89 | #define CMD_802_11_BEACON_CTRL 0x00b0 | 91 | #define CMD_802_11_BEACON_CTRL 0x00b0 |
90 | 92 | ||
91 | /* For the IEEE Power Save */ | 93 | /* For the IEEE Power Save */ |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e998c123e0c5..478d766abf8c 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); |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 89575e448015..a58a12352672 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1002,9 +1002,17 @@ static int lbs_setup_firmware(struct lbs_private *priv) | |||
1002 | { | 1002 | { |
1003 | int ret = -1; | 1003 | int ret = -1; |
1004 | s16 curlevel = 0, minlevel = 0, maxlevel = 0; | 1004 | s16 curlevel = 0, minlevel = 0, maxlevel = 0; |
1005 | struct cmd_header cmd; | ||
1005 | 1006 | ||
1006 | lbs_deb_enter(LBS_DEB_FW); | 1007 | lbs_deb_enter(LBS_DEB_FW); |
1007 | 1008 | ||
1009 | if (priv->fn_init_required) { | ||
1010 | memset(&cmd, 0, sizeof(cmd)); | ||
1011 | if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), | ||
1012 | lbs_cmd_copyback, (unsigned long) &cmd)) | ||
1013 | lbs_pr_alert("CMD_FUNC_INIT command failed\n"); | ||
1014 | } | ||
1015 | |||
1008 | /* Read MAC address from firmware */ | 1016 | /* Read MAC address from firmware */ |
1009 | memset(priv->current_addr, 0xff, ETH_ALEN); | 1017 | memset(priv->current_addr, 0xff, ETH_ALEN); |
1010 | ret = lbs_update_hw_spec(priv); | 1018 | ret = lbs_update_hw_spec(priv); |
@@ -1192,6 +1200,9 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1192 | priv->mesh_open = 0; | 1200 | priv->mesh_open = 0; |
1193 | priv->infra_open = 0; | 1201 | priv->infra_open = 0; |
1194 | 1202 | ||
1203 | priv->fn_init_required = 0; | ||
1204 | priv->fn_shutdown_required = 0; | ||
1205 | |||
1195 | /* Setup the OS Interface to our functions */ | 1206 | /* Setup the OS Interface to our functions */ |
1196 | dev->netdev_ops = &lbs_netdev_ops; | 1207 | dev->netdev_ops = &lbs_netdev_ops; |
1197 | dev->watchdog_timeo = 5 * HZ; | 1208 | dev->watchdog_timeo = 5 * HZ; |
@@ -1373,11 +1384,20 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1373 | struct net_device *dev; | 1384 | struct net_device *dev; |
1374 | struct cmd_ctrl_node *cmdnode; | 1385 | struct cmd_ctrl_node *cmdnode; |
1375 | unsigned long flags; | 1386 | unsigned long flags; |
1387 | struct cmd_header cmd; | ||
1376 | 1388 | ||
1377 | lbs_deb_enter(LBS_DEB_MAIN); | 1389 | lbs_deb_enter(LBS_DEB_MAIN); |
1378 | 1390 | ||
1379 | if (!priv) | 1391 | if (!priv) |
1380 | goto out; | 1392 | goto out; |
1393 | |||
1394 | if (priv->fn_shutdown_required) { | ||
1395 | memset(&cmd, 0, sizeof(cmd)); | ||
1396 | if (__lbs_cmd(priv, CMD_FUNC_SHUTDOWN, &cmd, sizeof(cmd), | ||
1397 | lbs_cmd_copyback, (unsigned long) &cmd)) | ||
1398 | lbs_pr_alert("CMD_FUNC_SHUTDOWN command failed\n"); | ||
1399 | } | ||
1400 | |||
1381 | dev = priv->dev; | 1401 | dev = priv->dev; |
1382 | 1402 | ||
1383 | netif_stop_queue(dev); | 1403 | netif_stop_queue(dev); |