aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c101
1 files changed, 55 insertions, 46 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index cb362b086ff6..dc3083ba8380 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2319,68 +2319,77 @@ static const struct iw_handler_def rndis_iw_handlers = {
2319}; 2319};
2320 2320
2321 2321
2322static void rndis_wlan_worker(struct work_struct *work) 2322static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2323{ 2323{
2324 struct rndis_wlan_private *priv =
2325 container_of(work, struct rndis_wlan_private, work);
2326 struct usbnet *usbdev = priv->usbdev;
2327 union iwreq_data evt;
2328 unsigned char bssid[ETH_ALEN];
2329 struct ndis_80211_assoc_info *info; 2324 struct ndis_80211_assoc_info *info;
2330 int assoc_size = sizeof(*info) + IW_CUSTOM_MAX + 32; 2325 union iwreq_data evt;
2326 u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32];
2327 u8 bssid[ETH_ALEN];
2331 int ret, offset; 2328 int ret, offset;
2332 2329
2333 if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending)) { 2330 memset(assoc_buf, 0, sizeof(assoc_buf));
2334 netif_carrier_on(usbdev->net); 2331 info = (void *)assoc_buf;
2335 2332
2336 info = kzalloc(assoc_size, GFP_KERNEL); 2333 netif_carrier_on(usbdev->net);
2337 if (!info) 2334
2338 goto get_bssid; 2335 /* Get association info IEs from device and send them back to
2339 2336 * userspace. */
2340 /* Get association info IEs from device and send them back to 2337 ret = get_association_info(usbdev, info, sizeof(assoc_buf));
2341 * userspace. */ 2338 if (!ret) {
2342 ret = get_association_info(usbdev, info, assoc_size); 2339 evt.data.length = le32_to_cpu(info->req_ie_length);
2343 if (!ret) { 2340 if (evt.data.length > 0) {
2344 evt.data.length = le32_to_cpu(info->req_ie_length); 2341 offset = le32_to_cpu(info->offset_req_ies);
2345 if (evt.data.length > 0) { 2342 wireless_send_event(usbdev->net,
2346 offset = le32_to_cpu(info->offset_req_ies); 2343 IWEVASSOCREQIE, &evt,
2347 wireless_send_event(usbdev->net, 2344 (char *)info + offset);
2348 IWEVASSOCREQIE, &evt,
2349 (char *)info + offset);
2350 }
2351
2352 evt.data.length = le32_to_cpu(info->resp_ie_length);
2353 if (evt.data.length > 0) {
2354 offset = le32_to_cpu(info->offset_resp_ies);
2355 wireless_send_event(usbdev->net,
2356 IWEVASSOCRESPIE, &evt,
2357 (char *)info + offset);
2358 }
2359 } 2345 }
2360 2346
2361 kfree(info); 2347 evt.data.length = le32_to_cpu(info->resp_ie_length);
2362 2348 if (evt.data.length > 0) {
2363get_bssid: 2349 offset = le32_to_cpu(info->offset_resp_ies);
2364 ret = get_bssid(usbdev, bssid); 2350 wireless_send_event(usbdev->net,
2365 if (!ret) { 2351 IWEVASSOCRESPIE, &evt,
2366 evt.data.flags = 0; 2352 (char *)info + offset);
2367 evt.data.length = 0;
2368 memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
2369 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
2370 } 2353 }
2371 2354
2372 usbnet_resume_rx(usbdev); 2355 usbnet_resume_rx(usbdev);
2373 } 2356 }
2374 2357
2375 if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) { 2358 ret = get_bssid(usbdev, bssid);
2376 netif_carrier_off(usbdev->net); 2359 if (!ret) {
2377
2378 evt.data.flags = 0; 2360 evt.data.flags = 0;
2379 evt.data.length = 0; 2361 evt.data.length = 0;
2380 memset(evt.ap_addr.sa_data, 0, ETH_ALEN); 2362 memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
2381 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); 2363 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
2382 } 2364 }
2383 2365
2366 usbnet_resume_rx(usbdev);
2367}
2368
2369static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)
2370{
2371 union iwreq_data evt;
2372
2373 netif_carrier_off(usbdev->net);
2374
2375 evt.data.flags = 0;
2376 evt.data.length = 0;
2377 memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
2378 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
2379}
2380
2381static void rndis_wlan_worker(struct work_struct *work)
2382{
2383 struct rndis_wlan_private *priv =
2384 container_of(work, struct rndis_wlan_private, work);
2385 struct usbnet *usbdev = priv->usbdev;
2386
2387 if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending))
2388 rndis_wlan_do_link_up_work(usbdev);
2389
2390 if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending))
2391 rndis_wlan_do_link_down_work(usbdev);
2392
2384 if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) 2393 if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
2385 set_multicast_list(usbdev); 2394 set_multicast_list(usbdev);
2386} 2395}