aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/libertas/dev.h2
-rw-r--r--drivers/net/wireless/libertas/host.h2
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c41
-rw-r--r--drivers/net/wireless/libertas/main.c20
4 files changed, 62 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index cbaafa653b6..a4455ec7c35 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
326extern struct cmd_confirm_sleep confirm_sleep; 328extern struct cmd_confirm_sleep confirm_sleep;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 8ff8ac9d817..fe8f0cb737b 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 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
66static struct if_sdio_model if_sdio_models[] = { 67static 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
541release: 545release:
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);
545release_fw: 548release_fw:
@@ -675,7 +678,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
675 ret = 0; 678 ret = 0;
676 679
677release: 680release:
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);
681release_fw: 683release_fw:
@@ -718,6 +720,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
718 goto out; 720 goto out;
719 721
720success: 722success:
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
723out: 728out:
@@ -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
1085static void __exit if_sdio_exit_module(void) 1105static 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 89575e44801..a58a1235267 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);