diff options
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 405 |
1 files changed, 162 insertions, 243 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ce1c18ee6280..6304bd97d399 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -791,7 +791,6 @@ static int libertas_thread(void *data) | |||
791 | } else | 791 | } else |
792 | spin_unlock_irq(&adapter->driver_lock); | 792 | spin_unlock_irq(&adapter->driver_lock); |
793 | 793 | ||
794 | |||
795 | lbs_deb_thread( | 794 | lbs_deb_thread( |
796 | "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " | 795 | "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " |
797 | "dnld_sent=%d\n", adapter->intcounter, | 796 | "dnld_sent=%d\n", adapter->intcounter, |
@@ -926,7 +925,7 @@ static int libertas_thread(void *data) | |||
926 | * @param priv A pointer to wlan_private structure | 925 | * @param priv A pointer to wlan_private structure |
927 | * @return 0 or -1 | 926 | * @return 0 or -1 |
928 | */ | 927 | */ |
929 | static int wlan_setup_station_hw(wlan_private * priv) | 928 | static int wlan_setup_firmware(wlan_private * priv) |
930 | { | 929 | { |
931 | int ret = -1; | 930 | int ret = -1; |
932 | wlan_adapter *adapter = priv->adapter; | 931 | wlan_adapter *adapter = priv->adapter; |
@@ -934,14 +933,6 @@ static int wlan_setup_station_hw(wlan_private * priv) | |||
934 | 933 | ||
935 | lbs_deb_enter(LBS_DEB_FW); | 934 | lbs_deb_enter(LBS_DEB_FW); |
936 | 935 | ||
937 | ret = priv->hw_prog_firmware(priv); | ||
938 | |||
939 | if (ret) { | ||
940 | lbs_deb_fw("bootloader in invalid state\n"); | ||
941 | ret = -1; | ||
942 | goto done; | ||
943 | } | ||
944 | |||
945 | /* | 936 | /* |
946 | * Read MAC address from HW | 937 | * Read MAC address from HW |
947 | */ | 938 | */ |
@@ -992,8 +983,6 @@ done: | |||
992 | return ret; | 983 | return ret; |
993 | } | 984 | } |
994 | 985 | ||
995 | static void command_timer_fn(unsigned long data); | ||
996 | |||
997 | /** | 986 | /** |
998 | * This function handles the timeout of command sending. | 987 | * This function handles the timeout of command sending. |
999 | * It will re-send the same command again. | 988 | * It will re-send the same command again. |
@@ -1035,155 +1024,99 @@ static void command_timer_fn(unsigned long data) | |||
1035 | return; | 1024 | return; |
1036 | } | 1025 | } |
1037 | 1026 | ||
1038 | static void libertas_free_adapter(wlan_private * priv) | 1027 | static int libertas_init_adapter(wlan_private * priv) |
1039 | { | 1028 | { |
1040 | wlan_adapter *adapter = priv->adapter; | 1029 | wlan_adapter *adapter = priv->adapter; |
1041 | |||
1042 | if (!adapter) { | ||
1043 | lbs_deb_fw("why double free adapter?\n"); | ||
1044 | return; | ||
1045 | } | ||
1046 | |||
1047 | lbs_deb_fw("free command buffer\n"); | ||
1048 | libertas_free_cmd_buffer(priv); | ||
1049 | |||
1050 | lbs_deb_fw("free command_timer\n"); | ||
1051 | del_timer(&adapter->command_timer); | ||
1052 | |||
1053 | lbs_deb_fw("free scan results table\n"); | ||
1054 | kfree(adapter->networks); | ||
1055 | adapter->networks = NULL; | ||
1056 | |||
1057 | /* Free the adapter object itself */ | ||
1058 | lbs_deb_fw("free adapter\n"); | ||
1059 | kfree(adapter); | ||
1060 | priv->adapter = NULL; | ||
1061 | } | ||
1062 | |||
1063 | static int wlan_allocate_adapter(wlan_private * priv) | ||
1064 | { | ||
1065 | size_t bufsize; | 1030 | size_t bufsize; |
1066 | wlan_adapter *adapter = priv->adapter; | 1031 | int i, ret = 0; |
1067 | 1032 | ||
1068 | /* Allocate buffer to store the BSSID list */ | 1033 | /* Allocate buffer to store the BSSID list */ |
1069 | bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); | 1034 | bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); |
1070 | adapter->networks = kzalloc(bufsize, GFP_KERNEL); | 1035 | adapter->networks = kzalloc(bufsize, GFP_KERNEL); |
1071 | if (!adapter->networks) { | 1036 | if (!adapter->networks) { |
1072 | lbs_pr_err("Out of memory allocating beacons\n"); | 1037 | lbs_pr_err("Out of memory allocating beacons\n"); |
1073 | libertas_free_adapter(priv); | 1038 | ret = -1; |
1074 | return -ENOMEM; | 1039 | goto out; |
1075 | } | 1040 | } |
1076 | 1041 | ||
1077 | /* Allocate the command buffers */ | 1042 | /* Initialize scan result lists */ |
1078 | libertas_allocate_cmd_buffer(priv); | 1043 | INIT_LIST_HEAD(&adapter->network_free_list); |
1044 | INIT_LIST_HEAD(&adapter->network_list); | ||
1045 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | ||
1046 | list_add_tail(&adapter->networks[i].list, | ||
1047 | &adapter->network_free_list); | ||
1048 | } | ||
1079 | 1049 | ||
1080 | memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep)); | ||
1081 | adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); | 1050 | adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); |
1082 | adapter->libertas_ps_confirm_sleep.command = | 1051 | adapter->libertas_ps_confirm_sleep.command = |
1083 | cpu_to_le16(CMD_802_11_PS_MODE); | 1052 | cpu_to_le16(CMD_802_11_PS_MODE); |
1084 | adapter->libertas_ps_confirm_sleep.size = | 1053 | adapter->libertas_ps_confirm_sleep.size = |
1085 | cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); | 1054 | cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); |
1086 | adapter->libertas_ps_confirm_sleep.result = 0; | ||
1087 | adapter->libertas_ps_confirm_sleep.action = | 1055 | adapter->libertas_ps_confirm_sleep.action = |
1088 | cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); | 1056 | cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); |
1089 | 1057 | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static void wlan_init_adapter(wlan_private * priv) | ||
1094 | { | ||
1095 | wlan_adapter *adapter = priv->adapter; | ||
1096 | int i; | ||
1097 | |||
1098 | adapter->connect_status = LIBERTAS_DISCONNECTED; | ||
1099 | memset(adapter->current_addr, 0xff, ETH_ALEN); | 1058 | memset(adapter->current_addr, 0xff, ETH_ALEN); |
1100 | 1059 | ||
1101 | /* 802.11 specific */ | 1060 | adapter->connect_status = LIBERTAS_DISCONNECTED; |
1102 | adapter->secinfo.wep_enabled = 0; | ||
1103 | for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]); | ||
1104 | i++) | ||
1105 | memset(&adapter->wep_keys[i], 0, sizeof(struct enc_key)); | ||
1106 | adapter->wep_tx_keyidx = 0; | ||
1107 | adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1061 | adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1108 | adapter->mode = IW_MODE_INFRA; | 1062 | adapter->mode = IW_MODE_INFRA; |
1109 | |||
1110 | adapter->pending_assoc_req = NULL; | ||
1111 | adapter->in_progress_assoc_req = NULL; | ||
1112 | |||
1113 | /* Initialize scan result lists */ | ||
1114 | INIT_LIST_HEAD(&adapter->network_free_list); | ||
1115 | INIT_LIST_HEAD(&adapter->network_list); | ||
1116 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | ||
1117 | list_add_tail(&adapter->networks[i].list, | ||
1118 | &adapter->network_free_list); | ||
1119 | } | ||
1120 | |||
1121 | mutex_init(&adapter->lock); | ||
1122 | |||
1123 | memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams)); | ||
1124 | adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1063 | adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1125 | 1064 | adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | |
1126 | /* PnP and power profile */ | ||
1127 | adapter->surpriseremoved = 0; | ||
1128 | |||
1129 | adapter->currentpacketfilter = | ||
1130 | CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | ||
1131 | |||
1132 | adapter->radioon = RADIO_ON; | 1065 | adapter->radioon = RADIO_ON; |
1133 | |||
1134 | adapter->auto_rate = 1; | 1066 | adapter->auto_rate = 1; |
1135 | adapter->cur_rate = 0; | ||
1136 | |||
1137 | // set default capabilities | ||
1138 | adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1067 | adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1139 | |||
1140 | adapter->psmode = WLAN802_11POWERMODECAM; | 1068 | adapter->psmode = WLAN802_11POWERMODECAM; |
1141 | |||
1142 | adapter->psstate = PS_STATE_FULL_POWER; | 1069 | adapter->psstate = PS_STATE_FULL_POWER; |
1143 | adapter->needtowakeup = 0; | ||
1144 | 1070 | ||
1145 | adapter->intcounter = 0; | 1071 | mutex_init(&adapter->lock); |
1146 | |||
1147 | adapter->currenttxskb = NULL; | ||
1148 | 1072 | ||
1149 | memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); | 1073 | memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); |
1150 | adapter->tx_queue_idx = 0; | 1074 | adapter->tx_queue_idx = 0; |
1151 | spin_lock_init(&adapter->txqueue_lock); | 1075 | spin_lock_init(&adapter->txqueue_lock); |
1152 | 1076 | ||
1153 | return; | 1077 | setup_timer(&adapter->command_timer, command_timer_fn, |
1154 | } | 1078 | (unsigned long)priv); |
1155 | 1079 | ||
1156 | static int libertas_init_fw(wlan_private * priv) | 1080 | INIT_LIST_HEAD(&adapter->cmdfreeq); |
1157 | { | 1081 | INIT_LIST_HEAD(&adapter->cmdpendingq); |
1158 | int ret = -1; | ||
1159 | wlan_adapter *adapter = priv->adapter; | ||
1160 | 1082 | ||
1161 | lbs_deb_enter(LBS_DEB_FW); | 1083 | spin_lock_init(&adapter->driver_lock); |
1084 | init_waitqueue_head(&adapter->cmd_pending); | ||
1085 | adapter->nr_cmd_pending = 0; | ||
1162 | 1086 | ||
1163 | /* Allocate adapter structure */ | 1087 | /* Allocate the command buffers */ |
1164 | if ((ret = wlan_allocate_adapter(priv)) != 0) | 1088 | if (libertas_allocate_cmd_buffer(priv)) { |
1165 | goto done; | 1089 | lbs_pr_err("Out of memory allocating command buffers\n"); |
1090 | ret = -1; | ||
1091 | } | ||
1166 | 1092 | ||
1167 | /* init adapter structure */ | 1093 | out: |
1168 | wlan_init_adapter(priv); | 1094 | return ret; |
1095 | } | ||
1169 | 1096 | ||
1170 | /* init timer etc. */ | 1097 | static void libertas_free_adapter(wlan_private * priv) |
1171 | setup_timer(&adapter->command_timer, command_timer_fn, | 1098 | { |
1172 | (unsigned long)priv); | 1099 | wlan_adapter *adapter = priv->adapter; |
1173 | 1100 | ||
1174 | /* download fimrware etc. */ | 1101 | if (!adapter) { |
1175 | if ((ret = wlan_setup_station_hw(priv)) != 0) { | 1102 | lbs_deb_fw("why double free adapter?\n"); |
1176 | del_timer_sync(&adapter->command_timer); | 1103 | return; |
1177 | goto done; | ||
1178 | } | 1104 | } |
1179 | 1105 | ||
1180 | /* init 802.11d */ | 1106 | lbs_deb_fw("free command buffer\n"); |
1181 | libertas_init_11d(priv); | 1107 | libertas_free_cmd_buffer(priv); |
1182 | 1108 | ||
1183 | ret = 0; | 1109 | lbs_deb_fw("free command_timer\n"); |
1184 | done: | 1110 | del_timer(&adapter->command_timer); |
1185 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 1111 | |
1186 | return ret; | 1112 | lbs_deb_fw("free scan results table\n"); |
1113 | kfree(adapter->networks); | ||
1114 | adapter->networks = NULL; | ||
1115 | |||
1116 | /* Free the adapter object itself */ | ||
1117 | lbs_deb_fw("free adapter\n"); | ||
1118 | kfree(adapter); | ||
1119 | priv->adapter = NULL; | ||
1187 | } | 1120 | } |
1188 | 1121 | ||
1189 | /** | 1122 | /** |
@@ -1203,9 +1136,9 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1203 | /* Allocate an Ethernet device and register it */ | 1136 | /* Allocate an Ethernet device and register it */ |
1204 | if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { | 1137 | if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { |
1205 | lbs_pr_err("init ethX device failed\n"); | 1138 | lbs_pr_err("init ethX device failed\n"); |
1206 | return NULL; | 1139 | goto done; |
1207 | } | 1140 | } |
1208 | priv = dev->priv; | 1141 | dmdev->driver_data = priv = dev->priv; |
1209 | 1142 | ||
1210 | /* allocate buffer for wlan_adapter */ | 1143 | /* allocate buffer for wlan_adapter */ |
1211 | if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { | 1144 | if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { |
@@ -1213,10 +1146,16 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1213 | goto err_kzalloc; | 1146 | goto err_kzalloc; |
1214 | } | 1147 | } |
1215 | 1148 | ||
1149 | if (libertas_init_adapter(priv)) { | ||
1150 | lbs_pr_err("failed to initialize adapter structure.\n"); | ||
1151 | goto err_init_adapter; | ||
1152 | } | ||
1153 | |||
1216 | priv->dev = dev; | 1154 | priv->dev = dev; |
1217 | priv->card = card; | 1155 | priv->card = card; |
1218 | priv->mesh_open = 0; | 1156 | priv->mesh_open = 0; |
1219 | priv->infra_open = 0; | 1157 | priv->infra_open = 0; |
1158 | priv->hotplug_device = dmdev; | ||
1220 | 1159 | ||
1221 | SET_MODULE_OWNER(dev); | 1160 | SET_MODULE_OWNER(dev); |
1222 | 1161 | ||
@@ -1239,87 +1178,144 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1239 | 1178 | ||
1240 | SET_NETDEV_DEV(dev, dmdev); | 1179 | SET_NETDEV_DEV(dev, dmdev); |
1241 | 1180 | ||
1242 | INIT_LIST_HEAD(&priv->adapter->cmdfreeq); | ||
1243 | INIT_LIST_HEAD(&priv->adapter->cmdpendingq); | ||
1244 | |||
1245 | spin_lock_init(&priv->adapter->driver_lock); | ||
1246 | init_waitqueue_head(&priv->adapter->cmd_pending); | ||
1247 | priv->adapter->nr_cmd_pending = 0; | ||
1248 | priv->rtap_net_dev = NULL; | 1181 | priv->rtap_net_dev = NULL; |
1249 | if (device_create_file(dmdev, &dev_attr_libertas_rtap)) | 1182 | if (device_create_file(dmdev, &dev_attr_libertas_rtap)) |
1250 | goto err_kzalloc; | 1183 | goto err_init_adapter; |
1184 | |||
1185 | lbs_deb_thread("Starting main thread...\n"); | ||
1186 | init_waitqueue_head(&priv->waitq); | ||
1187 | priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main"); | ||
1188 | if (IS_ERR(priv->main_thread)) { | ||
1189 | lbs_deb_thread("Error creating main thread.\n"); | ||
1190 | goto err_kthread_run; | ||
1191 | } | ||
1192 | |||
1193 | priv->work_thread = create_singlethread_workqueue("libertas_worker"); | ||
1194 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); | ||
1195 | INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker); | ||
1196 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); | ||
1197 | |||
1251 | goto done; | 1198 | goto done; |
1252 | 1199 | ||
1200 | err_kthread_run: | ||
1201 | device_remove_file(dmdev, &dev_attr_libertas_rtap); | ||
1202 | |||
1203 | err_init_adapter: | ||
1204 | libertas_free_adapter(priv); | ||
1205 | |||
1253 | err_kzalloc: | 1206 | err_kzalloc: |
1254 | free_netdev(dev); | 1207 | free_netdev(dev); |
1255 | priv = NULL; | 1208 | priv = NULL; |
1209 | |||
1256 | done: | 1210 | done: |
1257 | lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); | 1211 | lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); |
1258 | return priv; | 1212 | return priv; |
1259 | } | 1213 | } |
1260 | EXPORT_SYMBOL_GPL(libertas_add_card); | 1214 | EXPORT_SYMBOL_GPL(libertas_add_card); |
1261 | 1215 | ||
1262 | int libertas_activate_card(wlan_private *priv) | 1216 | |
1217 | int libertas_remove_card(wlan_private *priv) | ||
1263 | { | 1218 | { |
1219 | wlan_adapter *adapter = priv->adapter; | ||
1264 | struct net_device *dev = priv->dev; | 1220 | struct net_device *dev = priv->dev; |
1265 | int ret = -1; | 1221 | union iwreq_data wrqu; |
1266 | 1222 | ||
1267 | lbs_deb_enter(LBS_DEB_MAIN); | 1223 | lbs_deb_enter(LBS_DEB_MAIN); |
1268 | 1224 | ||
1269 | lbs_deb_thread("Starting main thread...\n"); | 1225 | libertas_remove_rtap(priv); |
1270 | init_waitqueue_head(&priv->waitq); | ||
1271 | priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main"); | ||
1272 | if (IS_ERR(priv->main_thread)) { | ||
1273 | lbs_deb_thread("Error creating main thread.\n"); | ||
1274 | goto done; | ||
1275 | } | ||
1276 | 1226 | ||
1277 | priv->work_thread = create_singlethread_workqueue("libertas_worker"); | 1227 | dev = priv->dev; |
1278 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); | 1228 | device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap); |
1279 | INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker); | ||
1280 | 1229 | ||
1281 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); | 1230 | cancel_delayed_work(&priv->scan_work); |
1231 | cancel_delayed_work(&priv->assoc_work); | ||
1232 | destroy_workqueue(priv->work_thread); | ||
1282 | 1233 | ||
1283 | /* | 1234 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { |
1284 | * Register the device. Fillup the private data structure with | 1235 | adapter->psmode = WLAN802_11POWERMODECAM; |
1285 | * relevant information from the card and request for the required | 1236 | libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); |
1286 | * IRQ. | ||
1287 | */ | ||
1288 | if (priv->hw_register_dev(priv) < 0) { | ||
1289 | lbs_pr_err("failed to register WLAN device\n"); | ||
1290 | goto err_registerdev; | ||
1291 | } | 1237 | } |
1292 | 1238 | ||
1293 | /* init FW and HW */ | 1239 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); |
1294 | if (libertas_init_fw(priv)) { | 1240 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
1295 | lbs_pr_err("firmware init failed\n"); | 1241 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); |
1296 | goto err_registerdev; | 1242 | |
1297 | } | 1243 | /* Stop the thread servicing the interrupts */ |
1244 | adapter->surpriseremoved = 1; | ||
1245 | kthread_stop(priv->main_thread); | ||
1246 | |||
1247 | libertas_free_adapter(priv); | ||
1248 | |||
1249 | priv->dev = NULL; | ||
1250 | free_netdev(dev); | ||
1251 | |||
1252 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1253 | return 0; | ||
1254 | } | ||
1255 | EXPORT_SYMBOL_GPL(libertas_remove_card); | ||
1256 | |||
1257 | |||
1258 | int libertas_start_card(wlan_private *priv) | ||
1259 | { | ||
1260 | struct net_device *dev = priv->dev; | ||
1261 | int ret = -1; | ||
1262 | |||
1263 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1264 | |||
1265 | /* poke the firmware */ | ||
1266 | ret = wlan_setup_firmware(priv); | ||
1267 | if (ret) | ||
1268 | goto done; | ||
1269 | |||
1270 | /* init 802.11d */ | ||
1271 | libertas_init_11d(priv); | ||
1298 | 1272 | ||
1299 | if (register_netdev(dev)) { | 1273 | if (register_netdev(dev)) { |
1300 | lbs_pr_err("cannot register ethX device\n"); | 1274 | lbs_pr_err("cannot register ethX device\n"); |
1301 | goto err_init_fw; | 1275 | goto done; |
1302 | } | 1276 | } |
1303 | 1277 | ||
1304 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | ||
1305 | |||
1306 | libertas_debugfs_init_one(priv, dev); | 1278 | libertas_debugfs_init_one(priv, dev); |
1307 | 1279 | ||
1280 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | ||
1281 | |||
1308 | ret = 0; | 1282 | ret = 0; |
1309 | goto done; | ||
1310 | 1283 | ||
1311 | err_init_fw: | ||
1312 | priv->hw_unregister_dev(priv); | ||
1313 | err_registerdev: | ||
1314 | destroy_workqueue(priv->work_thread); | ||
1315 | /* Stop the thread servicing the interrupts */ | ||
1316 | wake_up_interruptible(&priv->waitq); | ||
1317 | kthread_stop(priv->main_thread); | ||
1318 | done: | 1284 | done: |
1319 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); | 1285 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); |
1320 | return ret; | 1286 | return ret; |
1321 | } | 1287 | } |
1322 | EXPORT_SYMBOL_GPL(libertas_activate_card); | 1288 | EXPORT_SYMBOL_GPL(libertas_start_card); |
1289 | |||
1290 | |||
1291 | int libertas_stop_card(wlan_private *priv) | ||
1292 | { | ||
1293 | struct net_device *dev = priv->dev; | ||
1294 | int ret = -1; | ||
1295 | struct cmd_ctrl_node *cmdnode; | ||
1296 | unsigned long flags; | ||
1297 | |||
1298 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1299 | |||
1300 | netif_stop_queue(priv->dev); | ||
1301 | netif_carrier_off(priv->dev); | ||
1302 | |||
1303 | libertas_debugfs_remove_one(priv); | ||
1304 | |||
1305 | /* Flush pending command nodes */ | ||
1306 | spin_lock_irqsave(&priv->adapter->driver_lock, flags); | ||
1307 | list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { | ||
1308 | cmdnode->cmdwaitqwoken = 1; | ||
1309 | wake_up_interruptible(&cmdnode->cmdwait_q); | ||
1310 | } | ||
1311 | spin_unlock_irqrestore(&priv->adapter->driver_lock, flags); | ||
1312 | |||
1313 | unregister_netdev(dev); | ||
1314 | |||
1315 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1316 | return ret; | ||
1317 | } | ||
1318 | EXPORT_SYMBOL_GPL(libertas_stop_card); | ||
1323 | 1319 | ||
1324 | 1320 | ||
1325 | /** | 1321 | /** |
@@ -1389,89 +1385,12 @@ done: | |||
1389 | } | 1385 | } |
1390 | EXPORT_SYMBOL_GPL(libertas_add_mesh); | 1386 | EXPORT_SYMBOL_GPL(libertas_add_mesh); |
1391 | 1387 | ||
1392 | static void wake_pending_cmdnodes(wlan_private *priv) | ||
1393 | { | ||
1394 | struct cmd_ctrl_node *cmdnode; | ||
1395 | unsigned long flags; | ||
1396 | |||
1397 | lbs_deb_enter(LBS_DEB_HOST); | ||
1398 | |||
1399 | spin_lock_irqsave(&priv->adapter->driver_lock, flags); | ||
1400 | list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { | ||
1401 | cmdnode->cmdwaitqwoken = 1; | ||
1402 | wake_up_interruptible(&cmdnode->cmdwait_q); | ||
1403 | } | ||
1404 | spin_unlock_irqrestore(&priv->adapter->driver_lock, flags); | ||
1405 | } | ||
1406 | |||
1407 | |||
1408 | int libertas_remove_card(wlan_private *priv) | ||
1409 | { | ||
1410 | wlan_adapter *adapter; | ||
1411 | struct net_device *dev; | ||
1412 | union iwreq_data wrqu; | ||
1413 | |||
1414 | lbs_deb_enter(LBS_DEB_NET); | ||
1415 | |||
1416 | libertas_remove_rtap(priv); | ||
1417 | if (!priv) | ||
1418 | goto out; | ||
1419 | |||
1420 | adapter = priv->adapter; | ||
1421 | |||
1422 | if (!adapter) | ||
1423 | goto out; | ||
1424 | |||
1425 | dev = priv->dev; | ||
1426 | device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap); | ||
1427 | |||
1428 | netif_stop_queue(priv->dev); | ||
1429 | netif_carrier_off(priv->dev); | ||
1430 | |||
1431 | wake_pending_cmdnodes(priv); | ||
1432 | |||
1433 | unregister_netdev(dev); | ||
1434 | |||
1435 | cancel_delayed_work(&priv->scan_work); | ||
1436 | cancel_delayed_work(&priv->assoc_work); | ||
1437 | destroy_workqueue(priv->work_thread); | ||
1438 | |||
1439 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { | ||
1440 | adapter->psmode = WLAN802_11POWERMODECAM; | ||
1441 | libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | ||
1442 | } | ||
1443 | |||
1444 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); | ||
1445 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1446 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1447 | |||
1448 | adapter->surpriseremoved = 1; | ||
1449 | |||
1450 | /* Stop the thread servicing the interrupts */ | ||
1451 | kthread_stop(priv->main_thread); | ||
1452 | |||
1453 | libertas_debugfs_remove_one(priv); | ||
1454 | |||
1455 | lbs_deb_net("free adapter\n"); | ||
1456 | libertas_free_adapter(priv); | ||
1457 | |||
1458 | lbs_deb_net("unregister finish\n"); | ||
1459 | |||
1460 | priv->dev = NULL; | ||
1461 | free_netdev(dev); | ||
1462 | |||
1463 | out: | ||
1464 | lbs_deb_leave(LBS_DEB_NET); | ||
1465 | return 0; | ||
1466 | } | ||
1467 | EXPORT_SYMBOL_GPL(libertas_remove_card); | ||
1468 | |||
1469 | 1388 | ||
1470 | void libertas_remove_mesh(wlan_private *priv) | 1389 | void libertas_remove_mesh(wlan_private *priv) |
1471 | { | 1390 | { |
1472 | struct net_device *mesh_dev; | 1391 | struct net_device *mesh_dev; |
1473 | 1392 | ||
1474 | lbs_deb_enter(LBS_DEB_NET); | 1393 | lbs_deb_enter(LBS_DEB_MAIN); |
1475 | 1394 | ||
1476 | if (!priv) | 1395 | if (!priv) |
1477 | goto out; | 1396 | goto out; |
@@ -1488,7 +1407,7 @@ void libertas_remove_mesh(wlan_private *priv) | |||
1488 | free_netdev(mesh_dev); | 1407 | free_netdev(mesh_dev); |
1489 | 1408 | ||
1490 | out: | 1409 | out: |
1491 | lbs_deb_leave(LBS_DEB_NET); | 1410 | lbs_deb_leave(LBS_DEB_MAIN); |
1492 | } | 1411 | } |
1493 | EXPORT_SYMBOL_GPL(libertas_remove_mesh); | 1412 | EXPORT_SYMBOL_GPL(libertas_remove_mesh); |
1494 | 1413 | ||