2 * Linux cfg80211 driver - Dongle Host Driver (DHD) related
4 * Copyright (C) 1999-2016, Broadcom Corporation
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: dhd_cfg80211.c 591285 2015-10-07 11:56:29Z $
30 #include <linux/vmalloc.h>
31 #include <net/rtnetlink.h>
34 #include <wldev_common.h>
35 #include <wl_cfg80211.h>
36 #include <dhd_cfg80211.h>
38 #ifdef PKT_FILTER_SUPPORT
39 #include <dngl_stats.h>
43 extern struct bcm_cfg80211 *g_bcm_cfg;
45 #ifdef PKT_FILTER_SUPPORT
46 extern uint dhd_pkt_filter_enable;
47 extern uint dhd_master_mode;
48 extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
51 static int dhd_dongle_up = FALSE;
53 #include <dngl_stats.h>
57 #include <brcm_nl80211.h>
58 #include <dhd_cfg80211.h>
60 static s32 wl_dongle_up(struct net_device *ndev);
61 static s32 wl_dongle_down(struct net_device *ndev);
64 * Function implementations
67 s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
69 dhd_dongle_up = FALSE;
73 s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
75 dhd_dongle_up = FALSE;
79 s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
81 struct net_device *ndev;
86 WL_ERR(("Dongle is already down\n"));
90 ndev = bcmcfg_to_prmry_ndev(cfg);
92 dhd_dongle_up = FALSE;
96 s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
98 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
100 WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
101 #ifdef ARP_OFFLOAD_SUPPORT
102 if (dhd->arp_version == 1) {
103 /* IF P2P is enabled, disable arpoe */
104 dhd_arp_offload_set(dhd, 0);
105 dhd_arp_offload_enable(dhd, false);
107 #endif /* ARP_OFFLOAD_SUPPORT */
112 s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
114 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
115 dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
116 WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
118 #ifdef ARP_OFFLOAD_SUPPORT
119 if (dhd->arp_version == 1) {
120 /* IF P2P is disabled, enable arpoe back for STA mode. */
121 dhd_arp_offload_set(dhd, dhd_arp_mode);
122 dhd_arp_offload_enable(dhd, true);
124 #endif /* ARP_OFFLOAD_SUPPORT */
129 struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
130 uint8 *mac, uint8 bssidx, char *dngl_name)
132 return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE, dngl_name);
135 int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
137 return dhd_register_if(cfg->pub, ifidx, FALSE);
140 int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
142 return dhd_remove_if(cfg->pub, ifidx, FALSE);
145 struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
148 if (ndev->ieee80211_ptr) {
149 kfree(ndev->ieee80211_ptr);
150 ndev->ieee80211_ptr = NULL;
159 void dhd_netdev_free(struct net_device *ndev)
162 ndev = dhd_cfg80211_netdev_free(ndev);
169 wl_dongle_up(struct net_device *ndev)
174 err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
176 WL_ERR(("WLC_UP error (%d)\n", err));
182 wl_dongle_down(struct net_device *ndev)
187 err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true);
189 WL_ERR(("WLC_DOWN error (%d)\n", err));
195 s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
198 #define DHD_SDALIGN 32
200 struct net_device *ndev;
205 WL_ERR(("Dongle is already up\n"));
209 ndev = bcmcfg_to_prmry_ndev(cfg);
211 err = wl_dongle_up(ndev);
213 WL_ERR(("wl_dongle_up failed\n"));
214 goto default_conf_out;
216 dhd_dongle_up = true;
224 int dhd_cfgvendor_priv_string_handler(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev,
225 const struct bcm_nlmsg_hdr *nlioc, void *buf)
227 struct net_device *ndev = NULL;
229 dhd_ioctl_t ioc = { 0 };
233 WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
236 DHD_OS_WAKE_LOCK(dhd);
238 /* send to dongle only if we are not waiting for reload already */
239 if (dhd->hang_was_sent) {
240 WL_ERR(("HANG was sent up earlier\n"));
241 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
242 DHD_OS_WAKE_UNLOCK(dhd);
243 return OSL_ERROR(BCME_DONGLE_DOWN);
246 ndev = wdev_to_wlc_ndev(wdev, cfg);
247 index = dhd_net2idx(dhd->info, ndev);
248 if (index == DHD_BAD_IF) {
249 WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
254 ioc.cmd = nlioc->cmd;
255 ioc.len = nlioc->len;
256 ioc.set = nlioc->set;
257 ioc.driver = nlioc->magic;
258 ret = dhd_ioctl_process(dhd, index, &ioc, buf);
260 WL_TRACE(("dhd_ioctl_process return err %d\n", ret));
261 ret = OSL_ERROR(ret);
266 DHD_OS_WAKE_UNLOCK(dhd);