Merge tag 'v4.4-rc8'
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / dhd_cfg80211.c
1 /*
2  * Linux cfg80211 driver - Dongle Host Driver (DHD) related
3  *
4  * $Copyright Open Broadcom Corporation$
5  *
6  * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
7  */
8
9 #include <linux/vmalloc.h>
10 #include <net/rtnetlink.h>
11
12 #include <bcmutils.h>
13 #include <wldev_common.h>
14 #include <wl_cfg80211.h>
15 #include <dhd_cfg80211.h>
16
17 #ifdef PKT_FILTER_SUPPORT
18 #include <dngl_stats.h>
19 #include <dhd.h>
20 #endif
21
22 extern struct bcm_cfg80211 *g_bcm_cfg;
23
24 #ifdef PKT_FILTER_SUPPORT
25 extern uint dhd_pkt_filter_enable;
26 extern uint dhd_master_mode;
27 extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
28 #endif
29
30 static int dhd_dongle_up = FALSE;
31
32 #include <dngl_stats.h>
33 #include <dhd.h>
34 #include <dhdioctl.h>
35 #include <wlioctl.h>
36 #include <brcm_nl80211.h>
37 #include <dhd_cfg80211.h>
38
39 static s32 wl_dongle_up(struct net_device *ndev);
40 static s32 wl_dongle_down(struct net_device *ndev);
41
42 /**
43  * Function implementations
44  */
45
46 s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
47 {
48         dhd_dongle_up = FALSE;
49         return 0;
50 }
51
52 s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
53 {
54         dhd_dongle_up = FALSE;
55         return 0;
56 }
57
58 s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
59 {
60         struct net_device *ndev;
61         s32 err = 0;
62
63         WL_TRACE(("In\n"));
64         if (!dhd_dongle_up) {
65                 WL_ERR(("Dongle is already down\n"));
66                 return err;
67         }
68
69         ndev = bcmcfg_to_prmry_ndev(cfg);
70         wl_dongle_down(ndev);
71         dhd_dongle_up = FALSE;
72         return 0;
73 }
74
75 s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
76 {
77         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
78         dhd->op_mode |= val;
79         WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
80 #ifdef ARP_OFFLOAD_SUPPORT
81         if (dhd->arp_version == 1) {
82                 /* IF P2P is enabled, disable arpoe */
83                 dhd_arp_offload_set(dhd, 0);
84                 dhd_arp_offload_enable(dhd, false);
85         }
86 #endif /* ARP_OFFLOAD_SUPPORT */
87
88         return 0;
89 }
90
91 s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
92 {
93         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
94         dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
95         WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
96
97 #ifdef ARP_OFFLOAD_SUPPORT
98         if (dhd->arp_version == 1) {
99                 /* IF P2P is disabled, enable arpoe back for STA mode. */
100                 dhd_arp_offload_set(dhd, dhd_arp_mode);
101                 dhd_arp_offload_enable(dhd, true);
102         }
103 #endif /* ARP_OFFLOAD_SUPPORT */
104
105         return 0;
106 }
107
108 struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
109         uint8 *mac, uint8 bssidx)
110 {
111         return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE);
112 }
113
114 int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
115 {
116         return dhd_register_if(cfg->pub, ifidx, FALSE);
117 }
118
119 int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
120 {
121         return dhd_remove_if(cfg->pub, ifidx, FALSE);
122 }
123
124 struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
125 {
126         if (ndev) {
127                 if (ndev->ieee80211_ptr) {
128                         kfree(ndev->ieee80211_ptr);
129                         ndev->ieee80211_ptr = NULL;
130                 }
131                 free_netdev(ndev);
132                 return NULL;
133         }
134
135         return ndev;
136 }
137
138 void dhd_netdev_free(struct net_device *ndev)
139 {
140 #ifdef WL_CFG80211
141         ndev = dhd_cfg80211_netdev_free(ndev);
142 #endif
143         if (ndev)
144                 free_netdev(ndev);
145 }
146
147 static s32
148 wl_dongle_up(struct net_device *ndev)
149 {
150         s32 err = 0;
151         u32 up = 0;
152
153         err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
154         if (unlikely(err)) {
155                 WL_ERR(("WLC_UP error (%d)\n", err));
156         }
157         return err;
158 }
159
160 static s32
161 wl_dongle_down(struct net_device *ndev)
162 {
163         s32 err = 0;
164         u32 down = 0;
165
166         err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true);
167         if (unlikely(err)) {
168                 WL_ERR(("WLC_DOWN error (%d)\n", err));
169         }
170         return err;
171 }
172
173
174 s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
175 {
176 #ifndef DHD_SDALIGN
177 #define DHD_SDALIGN     32
178 #endif
179         struct net_device *ndev;
180         s32 err = 0;
181
182         WL_TRACE(("In\n"));
183         if (dhd_dongle_up) {
184                 WL_ERR(("Dongle is already up\n"));
185                 return err;
186         }
187
188         ndev = bcmcfg_to_prmry_ndev(cfg);
189
190         err = wl_dongle_up(ndev);
191         if (unlikely(err)) {
192                 WL_ERR(("wl_dongle_up failed\n"));
193                 goto default_conf_out;
194         }
195         dhd_dongle_up = true;
196
197 default_conf_out:
198
199         return err;
200
201 }