aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
commit33e2bf6aa16061bae1253514e7c32af27d2b4b31 (patch)
tree652d13b4feea9a8f562186e7badae72d2e22fe1f /drivers/net/wireless/rndis_wlan.c
parente880eb6c5c9d98e389ffc0d8947f75d70785361a (diff)
parent819bfecc4fc6b6e5a793f719a45b7146ce423b79 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/wireless/ath/ath5k/phy.c
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c364
1 files changed, 344 insertions, 20 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2887047069f2..aceb95ef7274 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -117,6 +117,7 @@ MODULE_PARM_DESC(workaround_interval,
117#define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d) 117#define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d)
118#define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e) 118#define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e)
119#define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f) 119#define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f)
120#define OID_802_11_CAPABILITY cpu_to_le32(0x0d010122)
120#define OID_802_11_PMKID cpu_to_le32(0x0d010123) 121#define OID_802_11_PMKID cpu_to_le32(0x0d010123)
121#define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203) 122#define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203)
122#define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204) 123#define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204)
@@ -358,6 +359,30 @@ struct ndis_80211_assoc_info {
358 __le32 offset_resp_ies; 359 __le32 offset_resp_ies;
359} __attribute__((packed)); 360} __attribute__((packed));
360 361
362struct ndis_80211_auth_encr_pair {
363 __le32 auth_mode;
364 __le32 encr_mode;
365} __attribute__((packed));
366
367struct ndis_80211_capability {
368 __le32 length;
369 __le32 version;
370 __le32 num_pmkids;
371 __le32 num_auth_encr_pair;
372 struct ndis_80211_auth_encr_pair auth_encr_pair[0];
373} __attribute__((packed));
374
375struct ndis_80211_bssid_info {
376 u8 bssid[6];
377 u8 pmkid[16];
378};
379
380struct ndis_80211_pmkid {
381 __le32 length;
382 __le32 bssid_info_count;
383 struct ndis_80211_bssid_info bssid_info[0];
384};
385
361/* 386/*
362 * private data 387 * private data
363 */ 388 */
@@ -476,13 +501,7 @@ struct rndis_wlan_private {
476 /* encryption stuff */ 501 /* encryption stuff */
477 int encr_tx_key_index; 502 int encr_tx_key_index;
478 struct rndis_wlan_encr_key encr_keys[4]; 503 struct rndis_wlan_encr_key encr_keys[4];
479 enum nl80211_auth_type wpa_auth_type;
480 int wpa_version; 504 int wpa_version;
481 int wpa_keymgmt;
482 int wpa_ie_len;
483 u8 *wpa_ie;
484 int wpa_cipher_pair;
485 int wpa_cipher_group;
486 505
487 u8 command_buffer[COMMAND_BUFFER_SIZE]; 506 u8 command_buffer[COMMAND_BUFFER_SIZE];
488}; 507};
@@ -534,6 +553,14 @@ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
534static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, 553static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
535 int idx, u8 *mac, struct station_info *sinfo); 554 int idx, u8 *mac, struct station_info *sinfo);
536 555
556static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
557 struct cfg80211_pmksa *pmksa);
558
559static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
560 struct cfg80211_pmksa *pmksa);
561
562static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
563
537static struct cfg80211_ops rndis_config_ops = { 564static struct cfg80211_ops rndis_config_ops = {
538 .change_virtual_intf = rndis_change_virtual_intf, 565 .change_virtual_intf = rndis_change_virtual_intf,
539 .scan = rndis_scan, 566 .scan = rndis_scan,
@@ -550,6 +577,9 @@ static struct cfg80211_ops rndis_config_ops = {
550 .set_default_key = rndis_set_default_key, 577 .set_default_key = rndis_set_default_key,
551 .get_station = rndis_get_station, 578 .get_station = rndis_get_station,
552 .dump_station = rndis_dump_station, 579 .dump_station = rndis_dump_station,
580 .set_pmksa = rndis_set_pmksa,
581 .del_pmksa = rndis_del_pmksa,
582 .flush_pmksa = rndis_flush_pmksa,
553}; 583};
554 584
555static void *rndis_wiphy_privid = &rndis_wiphy_privid; 585static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -704,6 +734,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
704 struct rndis_query_c *get_c; 734 struct rndis_query_c *get_c;
705 } u; 735 } u;
706 int ret, buflen; 736 int ret, buflen;
737 int resplen, respoffs, copylen;
707 738
708 buflen = *len + sizeof(*u.get); 739 buflen = *len + sizeof(*u.get);
709 if (buflen < CONTROL_BUFFER_SIZE) 740 if (buflen < CONTROL_BUFFER_SIZE)
@@ -733,11 +764,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
733 le32_to_cpu(u.get_c->status)); 764 le32_to_cpu(u.get_c->status));
734 765
735 if (ret == 0) { 766 if (ret == 0) {
736 memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); 767 resplen = le32_to_cpu(u.get_c->len);
768 respoffs = le32_to_cpu(u.get_c->offset) + 8;
737 769
738 ret = le32_to_cpu(u.get_c->len); 770 if (respoffs > buflen) {
739 if (ret > *len) 771 /* Device returned data offset outside buffer, error. */
740 *len = ret; 772 netdev_dbg(dev->net, "%s(%s): received invalid "
773 "data offset: %d > %d\n", __func__,
774 oid_to_string(oid), respoffs, buflen);
775
776 ret = -EINVAL;
777 goto exit_unlock;
778 }
779
780 if ((resplen + respoffs) > buflen) {
781 /* Device would have returned more data if buffer would
782 * have been big enough. Copy just the bits that we got.
783 */
784 copylen = buflen - respoffs;
785 } else {
786 copylen = resplen;
787 }
788
789 if (copylen > *len)
790 copylen = *len;
791
792 memcpy(data, u.buf + respoffs, copylen);
793
794 *len = resplen;
741 795
742 ret = rndis_error_status(u.get_c->status); 796 ret = rndis_error_status(u.get_c->status);
743 if (ret < 0) 797 if (ret < 0)
@@ -746,6 +800,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
746 le32_to_cpu(u.get_c->status), ret); 800 le32_to_cpu(u.get_c->status), ret);
747 } 801 }
748 802
803exit_unlock:
749 mutex_unlock(&priv->command_lock); 804 mutex_unlock(&priv->command_lock);
750 805
751 if (u.buf != priv->command_buffer) 806 if (u.buf != priv->command_buffer)
@@ -1091,8 +1146,6 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
1091 } 1146 }
1092 1147
1093 priv->wpa_version = wpa_version; 1148 priv->wpa_version = wpa_version;
1094 priv->wpa_auth_type = auth_type;
1095 priv->wpa_keymgmt = keymgmt;
1096 1149
1097 return 0; 1150 return 0;
1098} 1151}
@@ -1117,7 +1170,6 @@ static int set_priv_filter(struct usbnet *usbdev)
1117 1170
1118static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) 1171static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
1119{ 1172{
1120 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1121 __le32 tmp; 1173 __le32 tmp;
1122 int encr_mode, ret; 1174 int encr_mode, ret;
1123 1175
@@ -1146,8 +1198,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
1146 return ret; 1198 return ret;
1147 } 1199 }
1148 1200
1149 priv->wpa_cipher_pair = pairwise;
1150 priv->wpa_cipher_group = groupwise;
1151 return 0; 1201 return 0;
1152} 1202}
1153 1203
@@ -1568,6 +1618,194 @@ set_filter:
1568 le32_to_cpu(filter), ret); 1618 le32_to_cpu(filter), ret);
1569} 1619}
1570 1620
1621#ifdef DEBUG
1622static void debug_print_pmkids(struct usbnet *usbdev,
1623 struct ndis_80211_pmkid *pmkids,
1624 const char *func_str)
1625{
1626 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1627 int i, len, count, max_pmkids, entry_len;
1628
1629 max_pmkids = priv->wdev.wiphy->max_num_pmkids;
1630 len = le32_to_cpu(pmkids->length);
1631 count = le32_to_cpu(pmkids->bssid_info_count);
1632
1633 entry_len = (count > 0) ? (len - sizeof(*pmkids)) / count : -1;
1634
1635 netdev_dbg(usbdev->net, "%s(): %d PMKIDs (data len: %d, entry len: "
1636 "%d)\n", func_str, count, len, entry_len);
1637
1638 if (count > max_pmkids)
1639 count = max_pmkids;
1640
1641 for (i = 0; i < count; i++) {
1642 u32 *tmp = (u32 *)pmkids->bssid_info[i].pmkid;
1643
1644 netdev_dbg(usbdev->net, "%s(): bssid: %pM, "
1645 "pmkid: %08X:%08X:%08X:%08X\n",
1646 func_str, pmkids->bssid_info[i].bssid,
1647 cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
1648 cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
1649 }
1650}
1651#else
1652static void debug_print_pmkids(struct usbnet *usbdev,
1653 struct ndis_80211_pmkid *pmkids,
1654 const char *func_str)
1655{
1656 return;
1657}
1658#endif
1659
1660static struct ndis_80211_pmkid *get_device_pmkids(struct usbnet *usbdev)
1661{
1662 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1663 struct ndis_80211_pmkid *pmkids;
1664 int len, ret, max_pmkids;
1665
1666 max_pmkids = priv->wdev.wiphy->max_num_pmkids;
1667 len = sizeof(*pmkids) + max_pmkids * sizeof(pmkids->bssid_info[0]);
1668
1669 pmkids = kzalloc(len, GFP_KERNEL);
1670 if (!pmkids)
1671 return ERR_PTR(-ENOMEM);
1672
1673 pmkids->length = cpu_to_le32(len);
1674 pmkids->bssid_info_count = cpu_to_le32(max_pmkids);
1675
1676 ret = rndis_query_oid(usbdev, OID_802_11_PMKID, pmkids, &len);
1677 if (ret < 0) {
1678 netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d)"
1679 " -> %d\n", __func__, len, max_pmkids, ret);
1680
1681 kfree(pmkids);
1682 return ERR_PTR(ret);
1683 }
1684
1685 if (le32_to_cpu(pmkids->bssid_info_count) > max_pmkids)
1686 pmkids->bssid_info_count = cpu_to_le32(max_pmkids);
1687
1688 debug_print_pmkids(usbdev, pmkids, __func__);
1689
1690 return pmkids;
1691}
1692
1693static int set_device_pmkids(struct usbnet *usbdev,
1694 struct ndis_80211_pmkid *pmkids)
1695{
1696 int ret, len, num_pmkids;
1697
1698 num_pmkids = le32_to_cpu(pmkids->bssid_info_count);
1699 len = sizeof(*pmkids) + num_pmkids * sizeof(pmkids->bssid_info[0]);
1700 pmkids->length = cpu_to_le32(len);
1701
1702 debug_print_pmkids(usbdev, pmkids, __func__);
1703
1704 ret = rndis_set_oid(usbdev, OID_802_11_PMKID, pmkids,
1705 le32_to_cpu(pmkids->length));
1706 if (ret < 0) {
1707 netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d) -> %d"
1708 "\n", __func__, len, num_pmkids, ret);
1709 }
1710
1711 kfree(pmkids);
1712 return ret;
1713}
1714
1715static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev,
1716 struct ndis_80211_pmkid *pmkids,
1717 struct cfg80211_pmksa *pmksa,
1718 int max_pmkids)
1719{
1720 int i, len, count, newlen, err;
1721
1722 len = le32_to_cpu(pmkids->length);
1723 count = le32_to_cpu(pmkids->bssid_info_count);
1724
1725 if (count > max_pmkids)
1726 count = max_pmkids;
1727
1728 for (i = 0; i < count; i++)
1729 if (!compare_ether_addr(pmkids->bssid_info[i].bssid,
1730 pmksa->bssid))
1731 break;
1732
1733 /* pmkid not found */
1734 if (i == count) {
1735 netdev_dbg(usbdev->net, "%s(): bssid not found (%pM)\n",
1736 __func__, pmksa->bssid);
1737 err = -ENOENT;
1738 goto error;
1739 }
1740
1741 for (; i + 1 < count; i++)
1742 pmkids->bssid_info[i] = pmkids->bssid_info[i + 1];
1743
1744 count--;
1745 newlen = sizeof(*pmkids) + count * sizeof(pmkids->bssid_info[0]);
1746
1747 pmkids->length = cpu_to_le32(newlen);
1748 pmkids->bssid_info_count = cpu_to_le32(count);
1749
1750 return pmkids;
1751error:
1752 kfree(pmkids);
1753 return ERR_PTR(err);
1754}
1755
1756static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev,
1757 struct ndis_80211_pmkid *pmkids,
1758 struct cfg80211_pmksa *pmksa,
1759 int max_pmkids)
1760{
1761 int i, err, len, count, newlen;
1762
1763 len = le32_to_cpu(pmkids->length);
1764 count = le32_to_cpu(pmkids->bssid_info_count);
1765
1766 if (count > max_pmkids)
1767 count = max_pmkids;
1768
1769 /* update with new pmkid */
1770 for (i = 0; i < count; i++) {
1771 if (compare_ether_addr(pmkids->bssid_info[i].bssid,
1772 pmksa->bssid))
1773 continue;
1774
1775 memcpy(pmkids->bssid_info[i].pmkid, pmksa->pmkid,
1776 WLAN_PMKID_LEN);
1777
1778 return pmkids;
1779 }
1780
1781 /* out of space, return error */
1782 if (i == max_pmkids) {
1783 netdev_dbg(usbdev->net, "%s(): out of space\n", __func__);
1784 err = -ENOSPC;
1785 goto error;
1786 }
1787
1788 /* add new pmkid */
1789 newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]);
1790
1791 pmkids = krealloc(pmkids, newlen, GFP_KERNEL);
1792 if (!pmkids) {
1793 err = -ENOMEM;
1794 goto error;
1795 }
1796
1797 pmkids->length = cpu_to_le32(newlen);
1798 pmkids->bssid_info_count = cpu_to_le32(count + 1);
1799
1800 memcpy(pmkids->bssid_info[count].bssid, pmksa->bssid, ETH_ALEN);
1801 memcpy(pmkids->bssid_info[count].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
1802
1803 return pmkids;
1804error:
1805 kfree(pmkids);
1806 return ERR_PTR(err);
1807}
1808
1571/* 1809/*
1572 * cfg80211 ops 1810 * cfg80211 ops
1573 */ 1811 */
@@ -2178,6 +2416,78 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
2178 return 0; 2416 return 0;
2179} 2417}
2180 2418
2419static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
2420 struct cfg80211_pmksa *pmksa)
2421{
2422 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
2423 struct usbnet *usbdev = priv->usbdev;
2424 struct ndis_80211_pmkid *pmkids;
2425 u32 *tmp = (u32 *)pmksa->pmkid;
2426
2427 netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__,
2428 pmksa->bssid,
2429 cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
2430 cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
2431
2432 pmkids = get_device_pmkids(usbdev);
2433 if (IS_ERR(pmkids)) {
2434 /* couldn't read PMKID cache from device */
2435 return PTR_ERR(pmkids);
2436 }
2437
2438 pmkids = update_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids);
2439 if (IS_ERR(pmkids)) {
2440 /* not found, list full, etc */
2441 return PTR_ERR(pmkids);
2442 }
2443
2444 return set_device_pmkids(usbdev, pmkids);
2445}
2446
2447static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
2448 struct cfg80211_pmksa *pmksa)
2449{
2450 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
2451 struct usbnet *usbdev = priv->usbdev;
2452 struct ndis_80211_pmkid *pmkids;
2453 u32 *tmp = (u32 *)pmksa->pmkid;
2454
2455 netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__,
2456 pmksa->bssid,
2457 cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
2458 cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
2459
2460 pmkids = get_device_pmkids(usbdev);
2461 if (IS_ERR(pmkids)) {
2462 /* Couldn't read PMKID cache from device */
2463 return PTR_ERR(pmkids);
2464 }
2465
2466 pmkids = remove_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids);
2467 if (IS_ERR(pmkids)) {
2468 /* not found, etc */
2469 return PTR_ERR(pmkids);
2470 }
2471
2472 return set_device_pmkids(usbdev, pmkids);
2473}
2474
2475static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
2476{
2477 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
2478 struct usbnet *usbdev = priv->usbdev;
2479 struct ndis_80211_pmkid pmkid;
2480
2481 netdev_dbg(usbdev->net, "%s()\n", __func__);
2482
2483 memset(&pmkid, 0, sizeof(pmkid));
2484
2485 pmkid.length = cpu_to_le32(sizeof(pmkid));
2486 pmkid.bssid_info_count = cpu_to_le32(0);
2487
2488 return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
2489}
2490
2181/* 2491/*
2182 * workers, indication handlers, device poller 2492 * workers, indication handlers, device poller
2183 */ 2493 */
@@ -2522,12 +2832,14 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
2522 } 2832 }
2523} 2833}
2524 2834
2525static int rndis_wlan_get_caps(struct usbnet *usbdev) 2835static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy)
2526{ 2836{
2527 struct { 2837 struct {
2528 __le32 num_items; 2838 __le32 num_items;
2529 __le32 items[8]; 2839 __le32 items[8];
2530 } networks_supported; 2840 } networks_supported;
2841 struct ndis_80211_capability *caps;
2842 u8 caps_buf[sizeof(*caps) + sizeof(caps->auth_encr_pair) * 16];
2531 int len, retval, i, n; 2843 int len, retval, i, n;
2532 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 2844 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
2533 2845
@@ -2555,6 +2867,21 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev)
2555 } 2867 }
2556 } 2868 }
2557 2869
2870 /* get device 802.11 capabilities, number of PMKIDs */
2871 caps = (struct ndis_80211_capability *)caps_buf;
2872 len = sizeof(caps_buf);
2873 retval = rndis_query_oid(usbdev, OID_802_11_CAPABILITY, caps, &len);
2874 if (retval >= 0) {
2875 netdev_dbg(usbdev->net, "OID_802_11_CAPABILITY -> len %d, "
2876 "ver %d, pmkids %d, auth-encr-pairs %d\n",
2877 le32_to_cpu(caps->length),
2878 le32_to_cpu(caps->version),
2879 le32_to_cpu(caps->num_pmkids),
2880 le32_to_cpu(caps->num_auth_encr_pair));
2881 wiphy->max_num_pmkids = le32_to_cpu(caps->num_pmkids);
2882 } else
2883 wiphy->max_num_pmkids = 0;
2884
2558 return retval; 2885 return retval;
2559} 2886}
2560 2887
@@ -2802,7 +3129,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
2802 wiphy->max_scan_ssids = 1; 3129 wiphy->max_scan_ssids = 1;
2803 3130
2804 /* TODO: fill-out band/encr information based on priv->caps */ 3131 /* TODO: fill-out band/encr information based on priv->caps */
2805 rndis_wlan_get_caps(usbdev); 3132 rndis_wlan_get_caps(usbdev, wiphy);
2806 3133
2807 memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); 3134 memcpy(priv->channels, rndis_channels, sizeof(rndis_channels));
2808 memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); 3135 memcpy(priv->rates, rndis_rates, sizeof(rndis_rates));
@@ -2862,9 +3189,6 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
2862 flush_workqueue(priv->workqueue); 3189 flush_workqueue(priv->workqueue);
2863 destroy_workqueue(priv->workqueue); 3190 destroy_workqueue(priv->workqueue);
2864 3191
2865 if (priv && priv->wpa_ie_len)
2866 kfree(priv->wpa_ie);
2867
2868 rndis_unbind(usbdev, intf); 3192 rndis_unbind(usbdev, intf);
2869 3193
2870 wiphy_unregister(priv->wdev.wiphy); 3194 wiphy_unregister(priv->wdev.wiphy);