blob: 6e1ef99fc856353cfeadff38f3e7091308bdfd0e [file] [log] [blame]
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001#include "wilc_wfi_cfgoperations.h"
2#include "linux_wlan_common.h"
3#include "wilc_wlan_if.h"
4#include "wilc_wlan.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +09005
6#include <linux/slab.h>
7#include <linux/sched.h>
8#include <linux/delay.h>
9#include <linux/workqueue.h>
10#include <linux/interrupt.h>
11#include <linux/irq.h>
Guenter Roeckf1a99832015-05-27 13:02:16 -070012#include <linux/gpio.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090013
14#include <linux/kthread.h>
15#include <linux/firmware.h>
16#include <linux/delay.h>
17
18#include <linux/init.h>
19#include <linux/netdevice.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090020#include <linux/inetdevice.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090021#include <linux/etherdevice.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/skbuff.h>
25
Johnny Kimc5c77ba2015-05-11 14:30:56 +090026#include <linux/semaphore.h>
27
28#ifdef WILC_SDIO
29#include "linux_wlan_sdio.h"
30#else
31#include "linux_wlan_spi.h"
32#endif
33
Johnny Kimc5c77ba2015-05-11 14:30:56 +090034static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr);
35
36static struct notifier_block g_dev_notifier = {
37 .notifier_call = dev_state_ev_handler
38};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090039
Johnny Kimc5c77ba2015-05-11 14:30:56 +090040#define IRQ_WAIT 1
41#define IRQ_NO_WAIT 0
Johnny Kimc5c77ba2015-05-11 14:30:56 +090042static struct semaphore close_exit_sync;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090043
Glen Lee7c67c052015-10-27 18:27:50 +090044static int wlan_deinit_locks(struct net_device *dev);
Glen Lee32dd51b2015-10-27 18:27:52 +090045static void wlan_deinitialize_threads(struct net_device *dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090046
Johnny Kimc5c77ba2015-05-11 14:30:56 +090047static void linux_wlan_tx_complete(void *priv, int status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090048static int mac_init_fn(struct net_device *ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090049static struct net_device_stats *mac_stats(struct net_device *dev);
50static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
51static void wilc_set_multicast_list(struct net_device *dev);
Arnd Bergmann0e1af732015-11-16 15:04:54 +010052struct wilc *wilc_dev;
53bool wilc_enable_ps = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090054
Johnny Kimc5c77ba2015-05-11 14:30:56 +090055static const struct net_device_ops wilc_netdev_ops = {
56 .ndo_init = mac_init_fn,
Arnd Bergmann0e1af732015-11-16 15:04:54 +010057 .ndo_open = wilc_mac_open,
58 .ndo_stop = wilc_mac_close,
59 .ndo_start_xmit = wilc_mac_xmit,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090060 .ndo_do_ioctl = mac_ioctl,
61 .ndo_get_stats = mac_stats,
62 .ndo_set_rx_mode = wilc_set_multicast_list,
63
64};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090065
Johnny Kimc5c77ba2015-05-11 14:30:56 +090066static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr)
67{
68 struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr;
Chaehyun Lim27268872015-09-15 14:06:13 +090069 struct wilc_priv *priv;
Leo Kimf24374a2015-11-05 14:36:12 +090070 struct host_if_drv *hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090071 struct net_device *dev;
Leo Kimeac3e8f2015-11-05 14:36:16 +090072 u8 *ip_addr_buf;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090073 perInterface_wlan_t *nic;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +090074 u8 null_ip[4] = {0};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090075 char wlan_dev_name[5] = "wlan0";
76
Leo Kim3a147c02015-11-05 14:36:10 +090077 if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090078 PRINT_D(GENERIC_DBG, "dev_iface = NULL\n");
79 return NOTIFY_DONE;
80 }
81
Leo Kim582f8a22015-11-05 14:36:21 +090082 if (memcmp(dev_iface->ifa_label, "wlan0", 5) &&
83 memcmp(dev_iface->ifa_label, "p2p0", 4)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090084 PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n");
85 return NOTIFY_DONE;
86 }
87
88 dev = (struct net_device *)dev_iface->ifa_dev->dev;
Leo Kim3a147c02015-11-05 14:36:10 +090089 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090090 PRINT_D(GENERIC_DBG, "No Wireless registerd\n");
91 return NOTIFY_DONE;
92 }
93 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
Leo Kim3a147c02015-11-05 14:36:10 +090094 if (!priv) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090095 PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
96 return NOTIFY_DONE;
97 }
Leo Kimf24374a2015-11-05 14:36:12 +090098 hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090099 nic = netdev_priv(dev);
Leo Kimf24374a2015-11-05 14:36:12 +0900100 if (!nic || !hif_drv) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900101 PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
102 return NOTIFY_DONE;
103 }
104
Leo Kim98b89842015-11-05 14:36:18 +0900105 PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900106
107 switch (event) {
108 case NETDEV_UP:
Leo Kim98b89842015-11-05 14:36:18 +0900109 PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900110
111 PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
112
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900113 if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
Leo Kimf24374a2015-11-05 14:36:12 +0900114 hif_drv->IFC_UP = 1;
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100115 wilc_optaining_ip = false;
116 del_timer(&wilc_during_ip_timer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900117 PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
118 }
119
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100120 if (wilc_enable_ps)
121 wilc_set_power_mgmt(hif_drv, 1, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900122
123 PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
124
Leo Kimeac3e8f2015-11-05 14:36:16 +0900125 ip_addr_buf = (char *)&dev_iface->ifa_address;
126 PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
127 ip_addr_buf[0], ip_addr_buf[1],
128 ip_addr_buf[2], ip_addr_buf[3]);
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100129 wilc_setup_ipaddress(hif_drv, ip_addr_buf, nic->u8IfIdx);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900130
131 break;
132
133 case NETDEV_DOWN:
Leo Kim98b89842015-11-05 14:36:18 +0900134 PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900135
136 PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n");
137 if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
Leo Kimf24374a2015-11-05 14:36:12 +0900138 hif_drv->IFC_UP = 0;
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100139 wilc_optaining_ip = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900140 }
141
142 if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100143 wilc_set_power_mgmt(hif_drv, 0, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900144
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100145 wilc_resolve_disconnect_aberration(hif_drv);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900146
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900147 PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
148
Leo Kimeac3e8f2015-11-05 14:36:16 +0900149 ip_addr_buf = null_ip;
150 PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
151 ip_addr_buf[0], ip_addr_buf[1],
152 ip_addr_buf[2], ip_addr_buf[3]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900153
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100154 wilc_setup_ipaddress(hif_drv, ip_addr_buf, nic->u8IfIdx);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900155
156 break;
157
158 default:
Leo Kim98b89842015-11-05 14:36:18 +0900159 PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900160 PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event);
161
162 break;
163 }
164
165 return NOTIFY_DONE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900166}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900167
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900168#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
169static irqreturn_t isr_uh_routine(int irq, void *user_data)
170{
Glen Lee39483622015-10-27 18:27:37 +0900171 perInterface_wlan_t *nic;
172 struct wilc *wilc;
173 struct net_device *dev = (struct net_device *)user_data;
174
175 nic = netdev_priv(dev);
176 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900177 PRINT_D(INT_DBG, "Interrupt received UH\n");
178
Glen Lee39483622015-10-27 18:27:37 +0900179 if (wilc->close) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900180 PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900181 return IRQ_HANDLED;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900182 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900183 return IRQ_WAKE_THREAD;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900184}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900185
Arnd Bergmann1608c402015-11-16 15:04:53 +0100186static irqreturn_t isr_bh_routine(int irq, void *userdata)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900187{
Glen Lee2e7933d2015-10-27 18:27:38 +0900188 perInterface_wlan_t *nic;
189 struct wilc *wilc;
190
191 nic = netdev_priv(userdata);
192 wilc = nic->wilc;
193
Glen Lee2e7933d2015-10-27 18:27:38 +0900194 if (wilc->close) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900195 PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900196 return IRQ_HANDLED;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900197 }
198
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900199 PRINT_D(INT_DBG, "Interrupt received BH\n");
Glen Lee50b929e2015-10-27 18:27:40 +0900200 wilc_handle_isr(wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900201
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900202 return IRQ_HANDLED;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900203}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900204
Glen Lee2c1d05d2015-10-20 17:14:03 +0900205static int init_irq(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900206{
207 int ret = 0;
Glen Lee2c1d05d2015-10-20 17:14:03 +0900208 perInterface_wlan_t *nic;
209 struct wilc *wl;
210
211 nic = netdev_priv(dev);
212 wl = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900213
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900214 if ((gpio_request(GPIO_NUM, "WILC_INTR") == 0) &&
215 (gpio_direction_input(GPIO_NUM) == 0)) {
Glen Lee2c1d05d2015-10-20 17:14:03 +0900216 wl->dev_irq_num = gpio_to_irq(GPIO_NUM);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900217 } else {
218 ret = -1;
219 PRINT_ER("could not obtain gpio for WILC_INTR\n");
220 }
221
Leo Kim83231b72015-11-06 11:12:22 +0900222 if (ret != -1 && request_threaded_irq(wl->dev_irq_num,
223 isr_uh_routine,
224 isr_bh_routine,
225 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
226 "WILC_IRQ", dev) < 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900227 PRINT_ER("Failed to request IRQ for GPIO: %d\n", GPIO_NUM);
228 ret = -1;
229 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900230 PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
Glen Lee2c1d05d2015-10-20 17:14:03 +0900231 wl->dev_irq_num, GPIO_NUM);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900232 }
233
234 return ret;
235}
236#endif
237
Glen Leeec5cc752015-10-27 18:27:39 +0900238static void deinit_irq(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900239{
Glen Leeec5cc752015-10-27 18:27:39 +0900240 perInterface_wlan_t *nic;
241 struct wilc *wilc;
242
243 nic = netdev_priv(dev);
244 wilc = nic->wilc;
245
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900246#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
Glen Leeec5cc752015-10-27 18:27:39 +0900247 if (&wilc->dev_irq_num != 0) {
248 free_irq(wilc->dev_irq_num, wilc);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900249
250 gpio_free(GPIO_NUM);
251 }
252#endif
253}
254
Glen Leeef2b7842015-09-24 18:14:55 +0900255void linux_wlan_dbg(u8 *buff)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900256{
257 PRINT_D(INIT_DBG, "%d\n", *buff);
258}
259
Glen Leeb002e202015-09-24 18:15:05 +0900260int linux_wlan_lock_timeout(void *vp, u32 timeout)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900261{
262 int error = -1;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900263
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900264 PRINT_D(LOCK_DBG, "Locking %p\n", vp);
Leo Kim3a147c02015-11-05 14:36:10 +0900265 if (vp)
Leo Kim582f8a22015-11-05 14:36:21 +0900266 error = down_timeout((struct semaphore *)vp,
267 msecs_to_jiffies(timeout));
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530268 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900269 PRINT_ER("Failed, mutex is NULL\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900270 return error;
271}
272
Glen Lee64f2b712015-10-27 18:27:43 +0900273void linux_wlan_mac_indicate(struct wilc *wilc, int flag)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900274{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900275 int status;
276
277 if (flag == WILC_MAC_INDICATE_STATUS) {
Leo Kim582f8a22015-11-05 14:36:21 +0900278 wilc_wlan_cfg_get_val(WID_STATUS,
279 (unsigned char *)&status, 4);
Glen Lee64f2b712015-10-27 18:27:43 +0900280 if (wilc->mac_status == WILC_MAC_STATUS_INIT) {
281 wilc->mac_status = status;
282 up(&wilc->sync_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900283 } else {
Glen Lee64f2b712015-10-27 18:27:43 +0900284 wilc->mac_status = status;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900285 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900286 } else if (flag == WILC_MAC_INDICATE_SCAN) {
287 PRINT_D(GENERIC_DBG, "Scanning ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900288 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900289}
290
Arnd Bergmann1608c402015-11-16 15:04:53 +0100291static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900292{
Leo Kim660786e2015-11-05 14:36:27 +0900293 u8 *bssid, *bssid1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900294 int i = 0;
295
Leo Kimd2392222015-11-05 14:36:26 +0900296 bssid = mac_header + 10;
Leo Kim660786e2015-11-05 14:36:27 +0900297 bssid1 = mac_header + 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900298
Glen Lee4ad81fd2015-10-27 18:27:57 +0900299 for (i = 0; i < wilc->vif_num; i++)
Leo Kim660786e2015-11-05 14:36:27 +0900300 if (!memcmp(bssid1, wilc->vif[i].bssid, ETH_ALEN) ||
Leo Kimd2392222015-11-05 14:36:26 +0900301 !memcmp(bssid, wilc->vif[i].bssid, ETH_ALEN))
Glen Lee4ad81fd2015-10-27 18:27:57 +0900302 return wilc->vif[i].ndev;
Tony Cho8259a532015-10-20 14:26:47 +0900303
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900304 PRINT_INFO(INIT_DBG, "Invalide handle\n");
Kim, Leofc4b95d2015-07-28 17:47:37 +0900305 for (i = 0; i < 25; i++)
Leo Kim51456c22015-11-05 14:36:25 +0900306 PRINT_D(INIT_DBG, "%02x ", mac_header[i]);
Leo Kimd2392222015-11-05 14:36:26 +0900307 bssid = mac_header + 18;
Leo Kim660786e2015-11-05 14:36:27 +0900308 bssid1 = mac_header + 12;
Glen Lee4ad81fd2015-10-27 18:27:57 +0900309 for (i = 0; i < wilc->vif_num; i++)
Leo Kim660786e2015-11-05 14:36:27 +0900310 if (!memcmp(bssid1, wilc->vif[i].bssid, ETH_ALEN) ||
Leo Kimd2392222015-11-05 14:36:26 +0900311 !memcmp(bssid, wilc->vif[i].bssid, ETH_ALEN))
Glen Lee4ad81fd2015-10-27 18:27:57 +0900312 return wilc->vif[i].ndev;
Tony Cho8259a532015-10-20 14:26:47 +0900313
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900314 PRINT_INFO(INIT_DBG, "\n");
315 return NULL;
316}
317
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100318int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900319{
320 int i = 0;
321 int ret = -1;
Glen Lee472791a2015-10-27 18:27:44 +0900322 perInterface_wlan_t *nic;
323 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900324
Glen Lee472791a2015-10-27 18:27:44 +0900325 nic = netdev_priv(wilc_netdev);
326 wilc = nic->wilc;
327
328 for (i = 0; i < wilc->vif_num; i++)
329 if (wilc->vif[i].ndev == wilc_netdev) {
Leo Kimf66dee72015-11-05 14:36:28 +0900330 memcpy(wilc->vif[i].bssid, bssid, 6);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900331 ret = 0;
332 break;
333 }
Tony Cho8259a532015-10-20 14:26:47 +0900334
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900335 return ret;
336}
337
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100338int wilc_wlan_get_num_conn_ifcs(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900339{
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900340 u8 i = 0;
341 u8 null_bssid[6] = {0};
342 u8 ret_val = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900343
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100344 for (i = 0; i < wilc_dev->vif_num; i++)
345 if (memcmp(wilc_dev->vif[i].bssid, null_bssid, 6))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900346 ret_val++;
Tony Cho8259a532015-10-20 14:26:47 +0900347
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900348 return ret_val;
349}
350
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900351#define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
352
353static int linux_wlan_txq_task(void *vp)
354{
355 int ret, txq_count;
Glen Lee88687582015-10-27 18:27:46 +0900356 perInterface_wlan_t *nic;
357 struct wilc *wl;
358 struct net_device *dev = vp;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900359#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
360#define TX_BACKOFF_WEIGHT_INCR_STEP (1)
361#define TX_BACKOFF_WEIGHT_DECR_STEP (1)
362#define TX_BACKOFF_WEIGHT_MAX (7)
363#define TX_BACKOFF_WEIGHT_MIN (0)
364#define TX_BACKOFF_WEIGHT_UNIT_MS (10)
365 int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900366#endif
367
Glen Lee88687582015-10-27 18:27:46 +0900368 nic = netdev_priv(dev);
369 wl = nic->wilc;
370
Glen Lee88687582015-10-27 18:27:46 +0900371 up(&wl->txq_thread_started);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900372 while (1) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900373 PRINT_D(TX_DBG, "txq_task Taking a nap :)\n");
Glen Lee88687582015-10-27 18:27:46 +0900374 down(&wl->txq_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900375 PRINT_D(TX_DBG, "txq_task Who waked me up :$\n");
376
Glen Lee88687582015-10-27 18:27:46 +0900377 if (wl->close) {
Glen Lee88687582015-10-27 18:27:46 +0900378 up(&wl->txq_thread_started);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900379
380 while (!kthread_should_stop())
381 schedule();
382
383 PRINT_D(TX_DBG, "TX thread stopped\n");
384 break;
385 }
386 PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n");
387#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
Glen Leea1332ca2015-10-27 18:27:47 +0900388 ret = wilc_wlan_handle_txq(dev, &txq_count);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900389#else
390 do {
Glen Leea1332ca2015-10-27 18:27:47 +0900391 ret = wilc_wlan_handle_txq(dev, &txq_count);
Leo Kim98b89842015-11-05 14:36:18 +0900392 if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900393 PRINT_D(TX_DBG, "Waking up queue\n");
Leo Kim98b89842015-11-05 14:36:18 +0900394
Glen Lee88687582015-10-27 18:27:46 +0900395 if (netif_queue_stopped(wl->vif[0].ndev))
396 netif_wake_queue(wl->vif[0].ndev);
397 if (netif_queue_stopped(wl->vif[1].ndev))
398 netif_wake_queue(wl->vif[1].ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900399 }
400
Leo Kim98b89842015-11-05 14:36:18 +0900401 if (ret == WILC_TX_ERR_NO_BUF) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900402 do {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900403 msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
Leo Kim98b89842015-11-05 14:36:18 +0900404 } while (0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900405 backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
Kim, Leofc4b95d2015-07-28 17:47:37 +0900406 if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900407 backoff_weight = TX_BACKOFF_WEIGHT_MAX;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900408 } else {
409 if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) {
410 backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP;
Kim, Leofc4b95d2015-07-28 17:47:37 +0900411 if (backoff_weight < TX_BACKOFF_WEIGHT_MIN)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900412 backoff_weight = TX_BACKOFF_WEIGHT_MIN;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900413 }
414 }
Leo Kim98b89842015-11-05 14:36:18 +0900415 } while (ret == WILC_TX_ERR_NO_BUF && !wl->close);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900416#endif
417 }
418 return 0;
419}
420
Glen Leec0cadaa2015-09-24 18:14:54 +0900421void linux_wlan_rx_complete(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900422{
423 PRINT_D(RX_DBG, "RX completed\n");
424}
425
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100426int wilc_wlan_get_firmware(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900427{
Glen Lee65c8adc2015-10-29 12:18:49 +0900428 perInterface_wlan_t *nic;
429 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900430 int ret = 0;
431 const struct firmware *wilc_firmware;
432 char *firmware;
433
Glen Lee65c8adc2015-10-29 12:18:49 +0900434 nic = netdev_priv(dev);
435 wilc = nic->wilc;
436
Leo Kim1b7a93a2015-11-05 14:36:29 +0900437 if (nic->iftype == AP_MODE) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900438 firmware = AP_FIRMWARE;
Leo Kim1b7a93a2015-11-05 14:36:29 +0900439 } else if (nic->iftype == STATION_MODE) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900440 firmware = STA_FIRMWARE;
Leo Kim1b7a93a2015-11-05 14:36:29 +0900441 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900442 PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n");
443 firmware = P2P_CONCURRENCY_FIRMWARE;
444 }
445
Leo Kim3a147c02015-11-05 14:36:10 +0900446 if (!nic) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900447 PRINT_ER("NIC is NULL\n");
448 goto _fail_;
449 }
450
Leo Kim3a147c02015-11-05 14:36:10 +0900451 if (!(&nic->wilc_netdev->dev)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900452 PRINT_ER("&nic->wilc_netdev->dev is NULL\n");
453 goto _fail_;
454 }
455
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900456#ifdef WILC_SDIO
Glen Lee65c8adc2015-10-29 12:18:49 +0900457 if (request_firmware(&wilc_firmware, firmware, &wilc->wilc_sdio_func->dev) != 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900458 PRINT_ER("%s - firmare not available\n", firmware);
459 ret = -1;
460 goto _fail_;
461 }
462#else
Glen Lee65c8adc2015-10-29 12:18:49 +0900463 if (request_firmware(&wilc_firmware, firmware, &wilc->wilc_spidev->dev) != 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900464 PRINT_ER("%s - firmare not available\n", firmware);
465 ret = -1;
466 goto _fail_;
467 }
468#endif
Glen Lee65c8adc2015-10-29 12:18:49 +0900469 wilc->firmware = wilc_firmware;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900470
471_fail_:
472
473 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900474}
475
Glen Lee9bf3d722015-10-29 12:18:46 +0900476static int linux_wlan_start_firmware(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900477{
Glen Lee9bf3d722015-10-29 12:18:46 +0900478 perInterface_wlan_t *nic;
479 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900480 int ret = 0;
Glen Lee9bf3d722015-10-29 12:18:46 +0900481
482 nic = netdev_priv(dev);
483 wilc = nic->wilc;
484
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900485 PRINT_D(INIT_DBG, "Starting Firmware ...\n");
Glen Leee42563b2015-10-01 16:03:33 +0900486 ret = wilc_wlan_start();
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900487 if (ret < 0) {
488 PRINT_ER("Failed to start Firmware\n");
Leo Kim0aeea1a2015-11-05 14:36:30 +0900489 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900490 }
491
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900492 PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n");
Glen Lee9bf3d722015-10-29 12:18:46 +0900493 ret = linux_wlan_lock_timeout(&wilc->sync_event, 5000);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900494 if (ret) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900495 PRINT_D(INIT_DBG, "Firmware start timed out");
Leo Kim0aeea1a2015-11-05 14:36:30 +0900496 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900497 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900498 PRINT_D(INIT_DBG, "Firmware successfully started\n");
499
Leo Kim0aeea1a2015-11-05 14:36:30 +0900500 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900501}
Leo Kima40b22c2015-11-05 14:36:32 +0900502
Glen Leeed760b62015-10-29 12:18:42 +0900503static int linux_wlan_firmware_download(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900504{
Glen Leeed760b62015-10-29 12:18:42 +0900505 perInterface_wlan_t *nic;
506 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900507 int ret = 0;
508
Glen Leeed760b62015-10-29 12:18:42 +0900509 nic = netdev_priv(dev);
510 wilc = nic->wilc;
511
512 if (!wilc->firmware) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900513 PRINT_ER("Firmware buffer is NULL\n");
Leo Kim14b18212015-11-05 14:36:31 +0900514 return -ENOBUFS;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900515 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900516 PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
Glen Leeed760b62015-10-29 12:18:42 +0900517 ret = wilc_wlan_firmware_download(wilc->firmware->data,
518 wilc->firmware->size);
Kim, Leofc4b95d2015-07-28 17:47:37 +0900519 if (ret < 0)
Leo Kim14b18212015-11-05 14:36:31 +0900520 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900521
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900522 PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
523 PRINT_D(INIT_DBG, "Releasing firmware\n");
Glen Leeed760b62015-10-29 12:18:42 +0900524 release_firmware(wilc->firmware);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900525
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530526 PRINT_D(INIT_DBG, "Download Succeeded\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900527
Leo Kim14b18212015-11-05 14:36:31 +0900528 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900529}
530
Tony Chof61c5af2015-10-14 20:46:30 +0900531static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_nic)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900532{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900533 unsigned char c_val[64];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900534 unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff};
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900535
Chaehyun Lim27268872015-09-15 14:06:13 +0900536 struct wilc_priv *priv;
Leo Kim0fa66c72015-11-05 14:36:13 +0900537 struct host_if_drv *hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900538
539 PRINT_D(TX_DBG, "Start configuring Firmware\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900540 get_random_bytes(&mac_add[5], 1);
541 get_random_bytes(&mac_add[4], 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900542 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
Leo Kim0fa66c72015-11-05 14:36:13 +0900543 hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
544 PRINT_D(INIT_DBG, "Host = %p\n", hif_drv);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900545
Leo Kim582f8a22015-11-05 14:36:21 +0900546 PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n",
547 mac_add[0], mac_add[1], mac_add[2],
548 mac_add[3], mac_add[4], mac_add[5]);
Madhusudhanan Ravindran21175ef2015-06-09 11:19:06 +0000549 wilc_get_chipid(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900550
Johnny Kime5d57e92015-08-20 16:32:53 +0900551 *(int *)c_val = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900552
Glen Lee1028e5a2015-10-01 16:03:40 +0900553 if (!wilc_wlan_cfg_set(1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900554 goto _fail_;
555
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900556 c_val[0] = 0;
Glen Lee1028e5a2015-10-01 16:03:40 +0900557 if (!wilc_wlan_cfg_set(0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900558 goto _fail_;
559
560 c_val[0] = INFRASTRUCTURE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900561 if (!wilc_wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900562 goto _fail_;
563
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900564 c_val[0] = RATE_AUTO;
Glen Lee1028e5a2015-10-01 16:03:40 +0900565 if (!wilc_wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900566 goto _fail_;
567
568 c_val[0] = G_MIXED_11B_2_MODE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900569 if (!wilc_wlan_cfg_set(0, WID_11G_OPERATING_MODE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900570 goto _fail_;
571
572 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900573 if (!wilc_wlan_cfg_set(0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900574 goto _fail_;
575
576 c_val[0] = G_SHORT_PREAMBLE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900577 if (!wilc_wlan_cfg_set(0, WID_PREAMBLE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900578 goto _fail_;
579
580 c_val[0] = AUTO_PROT;
Glen Lee1028e5a2015-10-01 16:03:40 +0900581 if (!wilc_wlan_cfg_set(0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900582 goto _fail_;
583
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900584 c_val[0] = ACTIVE_SCAN;
Glen Lee1028e5a2015-10-01 16:03:40 +0900585 if (!wilc_wlan_cfg_set(0, WID_SCAN_TYPE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900586 goto _fail_;
587
588 c_val[0] = SITE_SURVEY_OFF;
Glen Lee1028e5a2015-10-01 16:03:40 +0900589 if (!wilc_wlan_cfg_set(0, WID_SITE_SURVEY, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900590 goto _fail_;
591
Leo Kim98b89842015-11-05 14:36:18 +0900592 *((int *)c_val) = 0xffff;
Glen Lee1028e5a2015-10-01 16:03:40 +0900593 if (!wilc_wlan_cfg_set(0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900594 goto _fail_;
595
596 *((int *)c_val) = 2346;
Glen Lee1028e5a2015-10-01 16:03:40 +0900597 if (!wilc_wlan_cfg_set(0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900598 goto _fail_;
599
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900600 c_val[0] = 0;
Glen Lee1028e5a2015-10-01 16:03:40 +0900601 if (!wilc_wlan_cfg_set(0, WID_BCAST_SSID, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900602 goto _fail_;
603
604 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900605 if (!wilc_wlan_cfg_set(0, WID_QOS_ENABLE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900606 goto _fail_;
607
608 c_val[0] = NO_POWERSAVE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900609 if (!wilc_wlan_cfg_set(0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900610 goto _fail_;
611
Arnd Bergmannb4d04c12015-11-16 15:04:56 +0100612 c_val[0] = NO_SECURITY; /* NO_ENCRYPT, 0x79 */
Glen Lee1028e5a2015-10-01 16:03:40 +0900613 if (!wilc_wlan_cfg_set(0, WID_11I_MODE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900614 goto _fail_;
615
616 c_val[0] = OPEN_SYSTEM;
Glen Lee1028e5a2015-10-01 16:03:40 +0900617 if (!wilc_wlan_cfg_set(0, WID_AUTH_TYPE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900618 goto _fail_;
619
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900620 strcpy(c_val, "123456790abcdef1234567890");
Glen Lee1028e5a2015-10-01 16:03:40 +0900621 if (!wilc_wlan_cfg_set(0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900622 goto _fail_;
623
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900624 strcpy(c_val, "12345678");
Glen Lee1028e5a2015-10-01 16:03:40 +0900625 if (!wilc_wlan_cfg_set(0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900626 goto _fail_;
627
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900628 strcpy(c_val, "password");
Glen Lee1028e5a2015-10-01 16:03:40 +0900629 if (!wilc_wlan_cfg_set(0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900630 goto _fail_;
631
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900632 c_val[0] = 192;
633 c_val[1] = 168;
634 c_val[2] = 1;
635 c_val[3] = 112;
Glen Lee1028e5a2015-10-01 16:03:40 +0900636 if (!wilc_wlan_cfg_set(0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900637 goto _fail_;
638
639 c_val[0] = 3;
Glen Lee1028e5a2015-10-01 16:03:40 +0900640 if (!wilc_wlan_cfg_set(0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900641 goto _fail_;
642
643 c_val[0] = 3;
Glen Lee1028e5a2015-10-01 16:03:40 +0900644 if (!wilc_wlan_cfg_set(0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900645 goto _fail_;
646
647 c_val[0] = NORMAL_ACK;
Glen Lee1028e5a2015-10-01 16:03:40 +0900648 if (!wilc_wlan_cfg_set(0, WID_ACK_POLICY, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900649 goto _fail_;
650
651 c_val[0] = 0;
Glen Lee1028e5a2015-10-01 16:03:40 +0900652 if (!wilc_wlan_cfg_set(0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900653 goto _fail_;
654
655 c_val[0] = 48;
Glen Lee1028e5a2015-10-01 16:03:40 +0900656 if (!wilc_wlan_cfg_set(0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900657 goto _fail_;
658
659 c_val[0] = 28;
Glen Lee1028e5a2015-10-01 16:03:40 +0900660 if (!wilc_wlan_cfg_set(0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900661 goto _fail_;
662
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900663 *((int *)c_val) = 100;
Glen Lee1028e5a2015-10-01 16:03:40 +0900664 if (!wilc_wlan_cfg_set(0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900665 goto _fail_;
666
667 c_val[0] = REKEY_DISABLE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900668 if (!wilc_wlan_cfg_set(0, WID_REKEY_POLICY, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900669 goto _fail_;
670
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900671 *((int *)c_val) = 84600;
Glen Lee1028e5a2015-10-01 16:03:40 +0900672 if (!wilc_wlan_cfg_set(0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900673 goto _fail_;
674
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900675 *((int *)c_val) = 500;
Glen Lee1028e5a2015-10-01 16:03:40 +0900676 if (!wilc_wlan_cfg_set(0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900677 goto _fail_;
678
679 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900680 if (!wilc_wlan_cfg_set(0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900681 goto _fail_;
682
683 c_val[0] = G_SELF_CTS_PROT;
Glen Lee1028e5a2015-10-01 16:03:40 +0900684 if (!wilc_wlan_cfg_set(0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900685 goto _fail_;
686
Leo Kim98b89842015-11-05 14:36:18 +0900687 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900688 if (!wilc_wlan_cfg_set(0, WID_11N_ENABLE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900689 goto _fail_;
690
691 c_val[0] = HT_MIXED_MODE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900692 if (!wilc_wlan_cfg_set(0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900693 goto _fail_;
694
Leo Kim98b89842015-11-05 14:36:18 +0900695 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900696 if (!wilc_wlan_cfg_set(0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900697 goto _fail_;
698
699 memcpy(c_val, mac_add, 6);
700
Glen Lee1028e5a2015-10-01 16:03:40 +0900701 if (!wilc_wlan_cfg_set(0, WID_MAC_ADDR, c_val, 6, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900702 goto _fail_;
703
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900704 c_val[0] = DETECT_PROTECT_REPORT;
Glen Lee1028e5a2015-10-01 16:03:40 +0900705 if (!wilc_wlan_cfg_set(0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900706 goto _fail_;
707
708 c_val[0] = RTS_CTS_NONHT_PROT;
Glen Lee1028e5a2015-10-01 16:03:40 +0900709 if (!wilc_wlan_cfg_set(0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900710 goto _fail_;
711
712 c_val[0] = 0;
Glen Lee1028e5a2015-10-01 16:03:40 +0900713 if (!wilc_wlan_cfg_set(0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900714 goto _fail_;
715
716 c_val[0] = MIMO_MODE;
Glen Lee1028e5a2015-10-01 16:03:40 +0900717 if (!wilc_wlan_cfg_set(0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900718 goto _fail_;
719
720 c_val[0] = 7;
Glen Lee1028e5a2015-10-01 16:03:40 +0900721 if (!wilc_wlan_cfg_set(0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900722 goto _fail_;
723
Leo Kim98b89842015-11-05 14:36:18 +0900724 c_val[0] = 1;
Glen Lee1028e5a2015-10-01 16:03:40 +0900725 if (!wilc_wlan_cfg_set(0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, 1))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900726 goto _fail_;
727
728 return 0;
729
730_fail_:
731 return -1;
732}
733
Glen Lee53dc0cf2015-10-20 17:13:57 +0900734void wilc1000_wlan_deinit(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900735{
Glen Lee53dc0cf2015-10-20 17:13:57 +0900736 perInterface_wlan_t *nic;
737 struct wilc *wl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900738
Glen Lee53dc0cf2015-10-20 17:13:57 +0900739 nic = netdev_priv(dev);
740 wl = nic->wilc;
741
742 if (!wl) {
743 netdev_err(dev, "wl is NULL\n");
744 return;
745 }
746
747 if (wl->initialized) {
748 netdev_info(dev, "Deinitializing wilc1000...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900749
750#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900751 PRINT_D(INIT_DBG, "skip wilc_bus_set_default_speed\n");
752#else
753 wilc_bus_set_default_speed();
754#endif
755
756 PRINT_D(INIT_DBG, "Disabling IRQ\n");
Glen Leed59177c2015-09-17 17:47:25 +0900757#ifdef WILC_SDIO
Glen Lee53dc0cf2015-10-20 17:13:57 +0900758 mutex_lock(&wl->hif_cs);
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100759 wilc_sdio_disable_interrupt();
Glen Lee53dc0cf2015-10-20 17:13:57 +0900760 mutex_unlock(&wl->hif_cs);
Glen Leed59177c2015-09-17 17:47:25 +0900761#endif
Leo Kim3a147c02015-11-05 14:36:10 +0900762 if (&wl->txq_event)
Glen Lee53dc0cf2015-10-20 17:13:57 +0900763 up(&wl->txq_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900764
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900765 PRINT_D(INIT_DBG, "Deinitializing Threads\n");
Glen Lee32dd51b2015-10-27 18:27:52 +0900766 wlan_deinitialize_threads(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900767
768 PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
Glen Leeec5cc752015-10-27 18:27:39 +0900769 deinit_irq(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900770
Glen Lee8cec7412015-10-01 16:03:34 +0900771 wilc_wlan_stop();
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900772
773 PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n");
Glen Lee2de7cbe2015-10-27 18:27:54 +0900774 wilc_wlan_cleanup(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900775#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
776 #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
777 PRINT_D(INIT_DBG, "Disabling IRQ 2\n");
778
Glen Lee53dc0cf2015-10-20 17:13:57 +0900779 mutex_lock(&wl->hif_cs);
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100780 wilc_sdio_disable_interrupt();
Glen Lee53dc0cf2015-10-20 17:13:57 +0900781 mutex_unlock(&wl->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900782 #endif
783#endif
784
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900785 PRINT_D(INIT_DBG, "Deinitializing Locks\n");
Glen Lee7c67c052015-10-27 18:27:50 +0900786 wlan_deinit_locks(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900787
Glen Lee53dc0cf2015-10-20 17:13:57 +0900788 wl->initialized = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900789
790 PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n");
791
792 } else {
793 PRINT_D(INIT_DBG, "wilc1000 is not initialized\n");
794 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900795}
796
Arnd Bergmann1608c402015-11-16 15:04:53 +0100797static int wlan_init_locks(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900798{
Glen Lee38afb392015-10-20 17:13:53 +0900799 perInterface_wlan_t *nic;
800 struct wilc *wl;
801
802 nic = netdev_priv(dev);
803 wl = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900804
805 PRINT_D(INIT_DBG, "Initializing Locks ...\n");
806
Glen Lee38afb392015-10-20 17:13:53 +0900807 mutex_init(&wl->hif_cs);
808 mutex_init(&wl->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900809
Glen Lee38afb392015-10-20 17:13:53 +0900810 spin_lock_init(&wl->txq_spinlock);
811 sema_init(&wl->txq_add_to_head_cs, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900812
Glen Lee38afb392015-10-20 17:13:53 +0900813 sema_init(&wl->txq_event, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900814
Glen Lee38afb392015-10-20 17:13:53 +0900815 sema_init(&wl->cfg_event, 0);
816 sema_init(&wl->sync_event, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900817
Glen Lee38afb392015-10-20 17:13:53 +0900818 sema_init(&wl->txq_thread_started, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900819
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900820 return 0;
821}
822
Glen Lee7c67c052015-10-27 18:27:50 +0900823static int wlan_deinit_locks(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900824{
Glen Lee7c67c052015-10-27 18:27:50 +0900825 perInterface_wlan_t *nic;
826 struct wilc *wilc;
827
828 nic = netdev_priv(dev);
829 wilc = nic->wilc;
830
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900831 PRINT_D(INIT_DBG, "De-Initializing Locks\n");
832
Leo Kim3a147c02015-11-05 14:36:10 +0900833 if (&wilc->hif_cs)
Glen Lee7c67c052015-10-27 18:27:50 +0900834 mutex_destroy(&wilc->hif_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900835
Leo Kim3a147c02015-11-05 14:36:10 +0900836 if (&wilc->rxq_cs)
Glen Lee7c67c052015-10-27 18:27:50 +0900837 mutex_destroy(&wilc->rxq_cs);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900838
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900839 return 0;
840}
Leo Kima40b22c2015-11-05 14:36:32 +0900841
Arnd Bergmann1608c402015-11-16 15:04:53 +0100842static void linux_to_wlan(wilc_wlan_inp_t *nwi, struct wilc *nic)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900843{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900844 PRINT_D(INIT_DBG, "Linux to Wlan services ...\n");
845
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900846#ifdef WILC_SDIO
847 nwi->io_func.io_type = HIF_SDIO;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900848#else
849 nwi->io_func.io_type = HIF_SPI;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900850#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900851}
852
Arnd Bergmann1608c402015-11-16 15:04:53 +0100853static int wlan_initialize_threads(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900854{
Glen Lee75a94662015-10-27 18:27:45 +0900855 perInterface_wlan_t *nic;
856 struct wilc *wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900857
Glen Lee75a94662015-10-27 18:27:45 +0900858 nic = netdev_priv(dev);
859 wilc = nic->wilc;
860
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900861 PRINT_D(INIT_DBG, "Initializing Threads ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900862 PRINT_D(INIT_DBG, "Creating kthread for transmission\n");
Glen Lee88687582015-10-27 18:27:46 +0900863 wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
Glen Lee75a94662015-10-27 18:27:45 +0900864 "K_TXQ_TASK");
865 if (!wilc->txq_thread) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900866 PRINT_ER("couldn't create TXQ thread\n");
Leo Kim6bc72c52015-11-05 14:36:33 +0900867 wilc->close = 0;
868 return -ENOBUFS;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900869 }
Glen Lee75a94662015-10-27 18:27:45 +0900870 down(&wilc->txq_thread_started);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900871
872 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900873}
874
Glen Lee32dd51b2015-10-27 18:27:52 +0900875static void wlan_deinitialize_threads(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900876{
Glen Lee32dd51b2015-10-27 18:27:52 +0900877 perInterface_wlan_t *nic;
878 struct wilc *wl;
Glen Lee32dd51b2015-10-27 18:27:52 +0900879 nic = netdev_priv(dev);
880 wl = nic->wilc;
881
882 wl->close = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900883 PRINT_D(INIT_DBG, "Deinitializing Threads\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900884
Leo Kim3a147c02015-11-05 14:36:10 +0900885 if (&wl->txq_event)
Glen Lee32dd51b2015-10-27 18:27:52 +0900886 up(&wl->txq_event);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900887
Leo Kim3a147c02015-11-05 14:36:10 +0900888 if (wl->txq_thread) {
Glen Lee32dd51b2015-10-27 18:27:52 +0900889 kthread_stop(wl->txq_thread);
890 wl->txq_thread = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900891 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900892}
893
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900894int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
895{
896 wilc_wlan_inp_t nwi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900897 perInterface_wlan_t *nic = p_nic;
898 int ret = 0;
Glen Lee0fa683b2015-10-20 17:13:52 +0900899 struct wilc *wl = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900900
Glen Lee0fa683b2015-10-20 17:13:52 +0900901 if (!wl->initialized) {
902 wl->mac_status = WILC_MAC_STATUS_INIT;
903 wl->close = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900904
Glen Lee38afb392015-10-20 17:13:53 +0900905 wlan_init_locks(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900906
Glen Lee0fa683b2015-10-20 17:13:52 +0900907 linux_to_wlan(&nwi, wl);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900908
Glen Lee47a466f2015-10-29 12:18:47 +0900909 ret = wilc_wlan_init(dev, &nwi);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900910 if (ret < 0) {
911 PRINT_ER("Initializing WILC_Wlan FAILED\n");
912 ret = -EIO;
913 goto _fail_locks_;
914 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900915
Tony Chob46d6882015-10-20 14:26:54 +0900916#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
Glen Lee2c1d05d2015-10-20 17:14:03 +0900917 if (init_irq(dev)) {
Tony Chob46d6882015-10-20 14:26:54 +0900918 PRINT_ER("couldn't initialize IRQ\n");
919 ret = -EIO;
920 goto _fail_locks_;
921 }
922#endif
923
Glen Lee75a94662015-10-27 18:27:45 +0900924 ret = wlan_initialize_threads(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900925 if (ret < 0) {
926 PRINT_ER("Initializing Threads FAILED\n");
927 ret = -EIO;
928 goto _fail_wilc_wlan_;
929 }
930
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900931#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100932 if (wilc_sdio_enable_interrupt()) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900933 PRINT_ER("couldn't initialize IRQ\n");
934 ret = -EIO;
935 goto _fail_irq_init_;
936 }
937#endif
938
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100939 if (wilc_wlan_get_firmware(dev)) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +0530940 PRINT_ER("Can't get firmware\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900941 ret = -EIO;
942 goto _fail_irq_enable_;
943 }
944
Glen Leeed760b62015-10-29 12:18:42 +0900945 ret = linux_wlan_firmware_download(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900946 if (ret < 0) {
947 PRINT_ER("Failed to download firmware\n");
948 ret = -EIO;
949 goto _fail_irq_enable_;
950 }
951
Glen Lee9bf3d722015-10-29 12:18:46 +0900952 ret = linux_wlan_start_firmware(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900953 if (ret < 0) {
954 PRINT_ER("Failed to start firmware\n");
955 ret = -EIO;
956 goto _fail_irq_enable_;
957 }
958
959 wilc_bus_set_max_speed();
960
Glen Lee07056a82015-10-01 16:03:41 +0900961 if (wilc_wlan_cfg_get(1, WID_FIRMWARE_VERSION, 1, 0)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900962 int size;
963 char Firmware_ver[20];
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900964
Glen Lee894de36b2015-10-01 16:03:42 +0900965 size = wilc_wlan_cfg_get_val(
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900966 WID_FIRMWARE_VERSION,
967 Firmware_ver, sizeof(Firmware_ver));
968 Firmware_ver[size] = '\0';
969 PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver);
970 }
Glen Lee0fa683b2015-10-20 17:13:52 +0900971 ret = linux_wlan_init_test_config(dev, wl);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900972
973 if (ret < 0) {
974 PRINT_ER("Failed to configure firmware\n");
975 ret = -EIO;
976 goto _fail_fw_start_;
977 }
978
Glen Lee0fa683b2015-10-20 17:13:52 +0900979 wl->initialized = true;
Leo Kim98b89842015-11-05 14:36:18 +0900980 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900981
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900982_fail_fw_start_:
Glen Lee8cec7412015-10-01 16:03:34 +0900983 wilc_wlan_stop();
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900984
985_fail_irq_enable_:
986#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100987 wilc_sdio_disable_interrupt();
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900988_fail_irq_init_:
Arnd Bergmann7a8fd842015-06-01 21:06:45 +0200989#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900990#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
Glen Leeec5cc752015-10-27 18:27:39 +0900991 deinit_irq(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900992
993#endif
Glen Lee32dd51b2015-10-27 18:27:52 +0900994 wlan_deinitialize_threads(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900995_fail_wilc_wlan_:
Glen Lee2de7cbe2015-10-27 18:27:54 +0900996 wilc_wlan_cleanup(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900997_fail_locks_:
Glen Lee7c67c052015-10-27 18:27:50 +0900998 wlan_deinit_locks(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900999 PRINT_ER("WLAN Iinitialization FAILED\n");
1000 } else {
1001 PRINT_D(INIT_DBG, "wilc1000 already initialized\n");
1002 }
1003 return ret;
1004}
1005
Arnd Bergmann1608c402015-11-16 15:04:53 +01001006static int mac_init_fn(struct net_device *ndev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001007{
Leo Kim98b89842015-11-05 14:36:18 +09001008 netif_start_queue(ndev);
1009 netif_stop_queue(ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001010
1011 return 0;
1012}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001013
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001014int wilc_mac_open(struct net_device *ndev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001015{
1016 perInterface_wlan_t *nic;
1017
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001018 unsigned char mac_add[ETH_ALEN] = {0};
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001019 int ret = 0;
1020 int i = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09001021 struct wilc_priv *priv;
Glen Leef3c13662015-10-20 17:13:54 +09001022 struct wilc *wl;
1023
1024 nic = netdev_priv(ndev);
1025 wl = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001026
Chandra S Gorentla7d056522015-09-15 18:09:51 +05301027#ifdef WILC_SPI
Leo Kim5191d772015-11-05 14:36:22 +09001028 if (!wl || !wl->wilc_spidev) {
Chandra S Gorentla7d056522015-09-15 18:09:51 +05301029 netdev_err(ndev, "wilc1000: SPI device not ready\n");
1030 return -ENODEV;
1031 }
1032#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001033 nic = netdev_priv(ndev);
1034 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
1035 PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev);
1036
Chaehyun Limdd4b6a82015-09-20 15:51:25 +09001037 ret = wilc_init_host_int(ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001038 if (ret < 0) {
1039 PRINT_ER("Failed to initialize host interface\n");
1040
1041 return ret;
1042 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001043
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001044 PRINT_D(INIT_DBG, "*** re-init ***\n");
1045 ret = wilc1000_wlan_init(ndev, nic);
1046 if (ret < 0) {
1047 PRINT_ER("Failed to initialize wilc1000\n");
Chaehyun Lima9a16822015-09-20 15:51:24 +09001048 wilc_deinit_host_int(ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001049 return ret;
1050 }
1051
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001052 wilc_set_machw_change_vir_if(ndev, false);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001053
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001054 wilc_get_mac_address(priv->hWILCWFIDrv, mac_add);
Alexander Kuleshov310a28f2015-09-04 00:48:14 +06001055 PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001056
Glen Leef3c13662015-10-20 17:13:54 +09001057 for (i = 0; i < wl->vif_num; i++) {
1058 if (ndev == wl->vif[i].ndev) {
1059 memcpy(wl->vif[i].src_addr, mac_add, ETH_ALEN);
1060 wl->vif[i].hif_drv = priv->hWILCWFIDrv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001061 break;
1062 }
1063 }
1064
Glen Leef3c13662015-10-20 17:13:54 +09001065 memcpy(ndev->dev_addr, wl->vif[i].src_addr, ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001066
1067 if (!is_valid_ether_addr(ndev->dev_addr)) {
1068 PRINT_ER("Error: Wrong MAC address\n");
Leo Kim339d2442015-11-05 14:36:34 +09001069 wilc_deinit_host_int(ndev);
1070 wilc1000_wlan_deinit(ndev);
1071 return -EINVAL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001072 }
1073
Leo Kim582f8a22015-11-05 14:36:21 +09001074 wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy,
1075 nic->wilc_netdev->ieee80211_ptr,
1076 nic->g_struct_frame_reg[0].frame_type,
1077 nic->g_struct_frame_reg[0].reg);
1078 wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy,
1079 nic->wilc_netdev->ieee80211_ptr,
1080 nic->g_struct_frame_reg[1].frame_type,
1081 nic->g_struct_frame_reg[1].reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001082 netif_wake_queue(ndev);
Glen Leef3c13662015-10-20 17:13:54 +09001083 wl->open_ifcs++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001084 nic->mac_opened = 1;
1085 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001086}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001087
Arnd Bergmann1608c402015-11-16 15:04:53 +01001088static struct net_device_stats *mac_stats(struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001089{
1090 perInterface_wlan_t *nic = netdev_priv(dev);
1091
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001092 return &nic->netstats;
1093}
1094
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001095static void wilc_set_multicast_list(struct net_device *dev)
1096{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001097 struct netdev_hw_addr *ha;
Chaehyun Lim27268872015-09-15 14:06:13 +09001098 struct wilc_priv *priv;
Leo Kimef7606c2015-11-05 14:36:14 +09001099 struct host_if_drv *hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001100 int i = 0;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001101
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001102 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
Leo Kimef7606c2015-11-05 14:36:14 +09001103 hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001104
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001105 if (!dev)
1106 return;
1107
Leo Kim582f8a22015-11-05 14:36:21 +09001108 PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n",
1109 dev->mc.count);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001110
1111 if (dev->flags & IFF_PROMISC) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +05301112 PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001113 return;
1114 }
1115
Leo Kim582f8a22015-11-05 14:36:21 +09001116 if ((dev->flags & IFF_ALLMULTI) ||
1117 (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001118 PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001119 wilc_setup_multicast_filter(hif_drv, false, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001120 return;
1121 }
1122
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001123 if ((dev->mc.count) == 0) {
1124 PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001125 wilc_setup_multicast_filter(hif_drv, true, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001126 return;
1127 }
1128
Leo Kimc8537e62015-11-06 11:12:24 +09001129 netdev_for_each_mc_addr(ha, dev) {
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001130 memcpy(wilc_multicast_mac_addr_list[i], ha->addr, ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001131 PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001132 wilc_multicast_mac_addr_list[i][0],
1133 wilc_multicast_mac_addr_list[i][1],
1134 wilc_multicast_mac_addr_list[i][2],
1135 wilc_multicast_mac_addr_list[i][3],
1136 wilc_multicast_mac_addr_list[i][4],
1137 wilc_multicast_mac_addr_list[i][5]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001138 i++;
1139 }
1140
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001141 wilc_setup_multicast_filter(hif_drv, true, (dev->mc.count));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001142
1143 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001144}
1145
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001146static void linux_wlan_tx_complete(void *priv, int status)
1147{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001148 struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001149
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301150 if (status == 1)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001151 PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301152 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001153 PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001154 dev_kfree_skb(pv_data->skb);
Greg Kroah-Hartmana18dd632015-09-03 19:04:19 -07001155 kfree(pv_data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001156}
1157
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001158int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001159{
1160 perInterface_wlan_t *nic;
1161 struct tx_complete_data *tx_data = NULL;
Leo Kim44ec3b72015-11-05 14:36:38 +09001162 int queue_count;
Leo Kimfd8f0362015-11-05 14:36:39 +09001163 char *udp_buf;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001164 struct iphdr *ih;
1165 struct ethhdr *eth_h;
Glen Leeb7495be2015-10-27 18:28:01 +09001166 struct wilc *wilc;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001167
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001168 nic = netdev_priv(ndev);
Glen Leeb7495be2015-10-27 18:28:01 +09001169 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001170
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001171 PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
1172
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001173 if (skb->dev != ndev) {
1174 PRINT_ER("Packet not destined to this device\n");
1175 return 0;
1176 }
1177
Leo Kimb38e9032015-11-06 11:12:23 +09001178 tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
Leo Kim3a147c02015-11-05 14:36:10 +09001179 if (!tx_data) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001180 PRINT_ER("Failed to allocate memory for tx_data structure\n");
1181 dev_kfree_skb(skb);
1182 netif_wake_queue(ndev);
1183 return 0;
1184 }
1185
1186 tx_data->buff = skb->data;
1187 tx_data->size = skb->len;
1188 tx_data->skb = skb;
1189
1190 eth_h = (struct ethhdr *)(skb->data);
Kim, Leofc4b95d2015-07-28 17:47:37 +09001191 if (eth_h->h_proto == 0x8e88)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001192 PRINT_D(INIT_DBG, "EAPOL transmitted\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001193
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001194 ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
1195
Leo Kimfd8f0362015-11-05 14:36:39 +09001196 udp_buf = (char *)ih + sizeof(struct iphdr);
1197 if ((udp_buf[1] == 68 && udp_buf[3] == 67) ||
1198 (udp_buf[1] == 67 && udp_buf[3] == 68))
1199 PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n",
1200 udp_buf[248], udp_buf[249], udp_buf[250]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001201
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001202 PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001203 PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n");
1204 nic->netstats.tx_packets++;
1205 nic->netstats.tx_bytes += tx_data->size;
Glen Leeb7495be2015-10-27 18:28:01 +09001206 tx_data->pBssid = wilc->vif[nic->u8IfIdx].bssid;
Leo Kim44ec3b72015-11-05 14:36:38 +09001207 queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
1208 tx_data->buff, tx_data->size,
1209 linux_wlan_tx_complete);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001210
Leo Kim44ec3b72015-11-05 14:36:38 +09001211 if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
Glen Leeb7495be2015-10-27 18:28:01 +09001212 netif_stop_queue(wilc->vif[0].ndev);
1213 netif_stop_queue(wilc->vif[1].ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001214 }
1215
1216 return 0;
1217}
1218
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001219int wilc_mac_close(struct net_device *ndev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001220{
Chaehyun Lim27268872015-09-15 14:06:13 +09001221 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001222 perInterface_wlan_t *nic;
Leo Kim2db2c8a2015-11-05 14:36:15 +09001223 struct host_if_drv *hif_drv;
Glen Leeca64ad62015-10-20 17:13:55 +09001224 struct wilc *wl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001225
1226 nic = netdev_priv(ndev);
1227
Leo Kim3a147c02015-11-05 14:36:10 +09001228 if (!nic || !nic->wilc_netdev || !nic->wilc_netdev->ieee80211_ptr ||
1229 !nic->wilc_netdev->ieee80211_ptr->wiphy) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001230 PRINT_ER("nic = NULL\n");
1231 return 0;
1232 }
1233
1234 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
Glen Leeca64ad62015-10-20 17:13:55 +09001235 wl = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001236
Leo Kim3a147c02015-11-05 14:36:10 +09001237 if (!priv) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001238 PRINT_ER("priv = NULL\n");
1239 return 0;
1240 }
1241
Leo Kim2db2c8a2015-11-05 14:36:15 +09001242 hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001243
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001244 PRINT_D(GENERIC_DBG, "Mac close\n");
1245
Glen Leeca64ad62015-10-20 17:13:55 +09001246 if (!wl) {
1247 PRINT_ER("wl = NULL\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001248 return 0;
1249 }
1250
Leo Kim2db2c8a2015-11-05 14:36:15 +09001251 if (!hif_drv) {
1252 PRINT_ER("hif_drv = NULL\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001253 return 0;
1254 }
1255
Glen Leeca64ad62015-10-20 17:13:55 +09001256 if ((wl->open_ifcs) > 0) {
1257 wl->open_ifcs--;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001258 } else {
1259 PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n");
1260 return 0;
1261 }
1262
Leo Kim3a147c02015-11-05 14:36:10 +09001263 if (nic->wilc_netdev) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001264 netif_stop_queue(nic->wilc_netdev);
1265
Chaehyun Lima9a16822015-09-20 15:51:24 +09001266 wilc_deinit_host_int(nic->wilc_netdev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001267 }
1268
Glen Leeca64ad62015-10-20 17:13:55 +09001269 if (wl->open_ifcs == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001270 PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n");
Glen Leeca64ad62015-10-20 17:13:55 +09001271 wl->close = 1;
Glen Lee53dc0cf2015-10-20 17:13:57 +09001272 wilc1000_wlan_deinit(ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001273 WILC_WFI_deinit_mon_interface();
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001274 }
1275
Greg Kroah-Hartman8990d852015-09-03 20:07:58 -07001276 up(&close_exit_sync);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001277 nic->mac_opened = 0;
1278
1279 return 0;
1280}
1281
Arnd Bergmann1608c402015-11-16 15:04:53 +01001282static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001283{
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +09001284 u8 *buff = NULL;
Chaehyun Limca356ad2015-06-11 14:35:57 +09001285 s8 rssi;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001286 u32 size = 0, length = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001287 perInterface_wlan_t *nic;
Chaehyun Lim27268872015-09-15 14:06:13 +09001288 struct wilc_priv *priv;
Leo Kim9457b052015-11-05 14:36:37 +09001289 s32 ret = 0;
Glen Lee07320b62015-10-27 18:27:53 +09001290 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001291
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001292 nic = netdev_priv(ndev);
Glen Lee07320b62015-10-27 18:27:53 +09001293 wilc = nic->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001294
Glen Lee07320b62015-10-27 18:27:53 +09001295 if (!wilc->initialized)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001296 return 0;
1297
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001298 switch (cmd) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001299 case SIOCSIWPRIV:
1300 {
Leo Kim98b89842015-11-05 14:36:18 +09001301 struct iwreq *wrq = (struct iwreq *) req;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001302
1303 size = wrq->u.data.length;
1304
1305 if (size && wrq->u.data.pointer) {
Leo Kim582f8a22015-11-05 14:36:21 +09001306 buff = memdup_user(wrq->u.data.pointer,
1307 wrq->u.data.length);
Sudip Mukherjee360e27a2015-09-04 15:34:15 +05301308 if (IS_ERR(buff))
1309 return PTR_ERR(buff);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001310
1311 if (strncasecmp(buff, "RSSI", length) == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001312 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001313 ret = wilc_get_rssi(priv->hWILCWFIDrv, &rssi);
Leo Kim9457b052015-11-05 14:36:37 +09001314 if (ret)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001315 PRINT_ER("Failed to send get rssi param's message queue ");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001316 PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi);
1317
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001318 rssi += 5;
1319
1320 snprintf(buff, size, "rssi %d", rssi);
1321
1322 if (copy_to_user(wrq->u.data.pointer, buff, size)) {
Chaehyun Lim60cb1e22015-06-19 09:06:28 +09001323 PRINT_ER("%s: failed to copy data to user buffer\n", __func__);
Leo Kim9457b052015-11-05 14:36:37 +09001324 ret = -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001325 goto done;
1326 }
1327 }
1328 }
1329 }
1330 break;
1331
1332 default:
1333 {
1334 PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd);
Leo Kim9457b052015-11-05 14:36:37 +09001335 ret = -EOPNOTSUPP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001336 goto done;
1337 }
1338 }
1339
1340done:
1341
Shraddha Barke642ac6c2015-08-10 13:30:33 +05301342 kfree(buff);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001343
Leo Kim9457b052015-11-05 14:36:37 +09001344 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001345}
1346
Glen Leecb1991a2015-10-27 18:27:56 +09001347void frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001348{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001349 unsigned int frame_len = 0;
1350 int stats;
1351 unsigned char *buff_to_send = NULL;
1352 struct sk_buff *skb;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001353 struct net_device *wilc_netdev;
1354 perInterface_wlan_t *nic;
1355
Leo Kim7e725b42015-11-05 14:36:24 +09001356 wilc_netdev = get_if_handler(wilc, buff);
Leo Kim3a147c02015-11-05 14:36:10 +09001357 if (!wilc_netdev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001358 return;
1359
1360 buff += pkt_offset;
1361 nic = netdev_priv(wilc_netdev);
1362
1363 if (size > 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001364 frame_len = size;
1365 buff_to_send = buff;
1366
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001367 skb = dev_alloc_skb(frame_len);
Leo Kim3a147c02015-11-05 14:36:10 +09001368 if (!skb) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001369 PRINT_ER("Low memory - packet droped\n");
1370 return;
1371 }
1372
Leo Kim3a147c02015-11-05 14:36:10 +09001373 if (!wilc || !wilc_netdev)
Glen Leecb1991a2015-10-27 18:27:56 +09001374 PRINT_ER("wilc_netdev in wilc is NULL");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001375 skb->dev = wilc_netdev;
1376
Leo Kim3a147c02015-11-05 14:36:10 +09001377 if (!skb->dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001378 PRINT_ER("skb->dev is NULL\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001379
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001380 memcpy(skb_put(skb, frame_len), buff_to_send, frame_len);
1381
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001382 skb->protocol = eth_type_trans(skb, wilc_netdev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001383 nic->netstats.rx_packets++;
1384 nic->netstats.rx_bytes += frame_len;
1385 skb->ip_summed = CHECKSUM_UNNECESSARY;
1386 stats = netif_rx(skb);
1387 PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats);
1388 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001389}
1390
Glen Lee11f4b2e2015-10-27 18:27:51 +09001391void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001392{
1393 int i = 0;
1394 perInterface_wlan_t *nic;
1395
Glen Lee11f4b2e2015-10-27 18:27:51 +09001396 for (i = 0; i < wilc->vif_num; i++) {
1397 nic = netdev_priv(wilc->vif[i].ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001398 if (nic->monitor_flag) {
1399 WILC_WFI_monitor_rx(buff, size);
1400 return;
1401 }
1402 }
1403
Leo Kim98b89842015-11-05 14:36:18 +09001404 nic = netdev_priv(wilc->vif[1].ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001405 if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) ||
Kim, Leofc4b95d2015-07-28 17:47:37 +09001406 (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg))
Glen Lee11f4b2e2015-10-27 18:27:51 +09001407 WILC_WFI_p2p_rx(wilc->vif[1].ndev, buff, size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001408}
1409
Glen Lee90b984c2015-10-29 12:18:50 +09001410void wl_wlan_cleanup(struct wilc *wilc)
Tony Cho4875c492015-10-20 14:26:52 +09001411{
1412 int i = 0;
1413 perInterface_wlan_t *nic[NUM_CONCURRENT_IFC];
1414
Leo Kim83231b72015-11-06 11:12:22 +09001415 if (wilc && (wilc->vif[0].ndev || wilc->vif[1].ndev)) {
Tony Cho4875c492015-10-20 14:26:52 +09001416 unregister_inetaddr_notifier(&g_dev_notifier);
1417
1418 for (i = 0; i < NUM_CONCURRENT_IFC; i++)
Glen Lee90b984c2015-10-29 12:18:50 +09001419 nic[i] = netdev_priv(wilc->vif[i].ndev);
Tony Cho4875c492015-10-20 14:26:52 +09001420 }
1421
Glen Lee90b984c2015-10-29 12:18:50 +09001422 if (wilc && wilc->firmware)
1423 release_firmware(wilc->firmware);
Tony Cho4875c492015-10-20 14:26:52 +09001424
Leo Kim5191d772015-11-05 14:36:22 +09001425 if (wilc && (wilc->vif[0].ndev || wilc->vif[1].ndev)) {
Tony Cho4875c492015-10-20 14:26:52 +09001426 linux_wlan_lock_timeout(&close_exit_sync, 12 * 1000);
1427
1428 for (i = 0; i < NUM_CONCURRENT_IFC; i++)
Glen Lee90b984c2015-10-29 12:18:50 +09001429 if (wilc->vif[i].ndev)
Tony Cho4875c492015-10-20 14:26:52 +09001430 if (nic[i]->mac_opened)
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001431 wilc_mac_close(wilc->vif[i].ndev);
Tony Cho4875c492015-10-20 14:26:52 +09001432
1433 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
Glen Lee90b984c2015-10-29 12:18:50 +09001434 unregister_netdev(wilc->vif[i].ndev);
1435 wilc_free_wiphy(wilc->vif[i].ndev);
1436 free_netdev(wilc->vif[i].ndev);
Tony Cho4875c492015-10-20 14:26:52 +09001437 }
1438 }
1439
Glen Lee90b984c2015-10-29 12:18:50 +09001440 kfree(wilc);
Tony Cho4875c492015-10-20 14:26:52 +09001441
1442#if defined(WILC_DEBUGFS)
1443 wilc_debugfs_remove();
1444#endif
Tony Cho4875c492015-10-20 14:26:52 +09001445}
1446
Tony Cho12ba5412015-10-20 14:26:56 +09001447int wilc_netdev_init(struct wilc **wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001448{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001449 int i;
1450 perInterface_wlan_t *nic;
1451 struct net_device *ndev;
1452
Greg Kroah-Hartman642768e2015-09-03 19:56:21 -07001453 sema_init(&close_exit_sync, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001454
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001455 wilc_dev = kzalloc(sizeof(*wilc_dev), GFP_KERNEL);
1456 if (!wilc_dev)
Chaehyun Limac61ef82015-09-08 00:36:36 +09001457 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001458
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001459 *wilc = wilc_dev;
Tony Cho12ba5412015-10-20 14:26:56 +09001460
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001461 register_inetaddr_notifier(&g_dev_notifier);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001462
1463 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001464 ndev = alloc_etherdev(sizeof(perInterface_wlan_t));
1465 if (!ndev) {
1466 PRINT_ER("Failed to allocate ethernet dev\n");
1467 return -1;
1468 }
1469
1470 nic = netdev_priv(ndev);
1471 memset(nic, 0, sizeof(perInterface_wlan_t));
1472
Leo Kim84d3b872015-11-05 14:36:19 +09001473 if (i == 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001474 strcpy(ndev->name, "wlan%d");
Leo Kim84d3b872015-11-05 14:36:19 +09001475 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001476 strcpy(ndev->name, "p2p%d");
1477
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001478 nic->u8IfIdx = wilc_dev->vif_num;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001479 nic->wilc_netdev = ndev;
Glen Lee38b3001d2015-10-20 17:13:51 +09001480 nic->wilc = *wilc;
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001481 wilc_dev->vif[wilc_dev->vif_num].ndev = ndev;
1482 wilc_dev->vif_num++;
Arnd Bergmanne5af0562015-05-29 22:52:12 +02001483 ndev->netdev_ops = &wilc_netdev_ops;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001484
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001485 {
1486 struct wireless_dev *wdev;
Chaehyun Lim8459fd52015-09-20 15:51:09 +09001487 wdev = wilc_create_wiphy(ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001488
1489 #ifdef WILC_SDIO
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001490 SET_NETDEV_DEV(ndev, &wilc_sdio_func->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001491 #endif
1492
Leo Kim3a147c02015-11-05 14:36:10 +09001493 if (!wdev) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001494 PRINT_ER("Can't register WILC Wiphy\n");
1495 return -1;
1496 }
1497
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001498 nic->wilc_netdev->ieee80211_ptr = wdev;
1499 nic->wilc_netdev->ml_priv = nic;
1500 wdev->netdev = nic->wilc_netdev;
1501 nic->netstats.rx_packets = 0;
1502 nic->netstats.tx_packets = 0;
1503 nic->netstats.rx_bytes = 0;
1504 nic->netstats.tx_bytes = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001505 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001506
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001507 if (register_netdev(ndev)) {
Leo Kim582f8a22015-11-05 14:36:21 +09001508 PRINT_ER("Device couldn't be registered - %s\n",
1509 ndev->name);
Leo Kim98b89842015-11-05 14:36:18 +09001510 return -1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001511 }
1512
1513 nic->iftype = STATION_MODE;
1514 nic->mac_opened = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001515 }
1516
1517 #ifndef WILC_SDIO
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001518 if (!wilc_spi_init()) {
Chandra S Gorentla17aacd42015-08-08 17:41:35 +05301519 PRINT_ER("Can't initialize SPI\n");
Leo Kim98b89842015-11-05 14:36:18 +09001520 return -1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001521 }
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001522 wilc_dev->wilc_spidev = wilc_spi_dev;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001523 #else
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001524 wilc_dev->wilc_sdio_func = wilc_sdio_func;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001525 #endif
1526
1527 return 0;
1528}
1529
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001530static int __init init_wilc_driver(void)
1531{
Glen Lee702c0e52015-10-27 18:20:14 +09001532#ifdef WILC_SPI
1533 struct wilc *wilc;
1534#endif
1535
Kim, Leo33694632015-07-28 17:47:39 +09001536#if defined(WILC_DEBUGFS)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001537 if (wilc_debugfs_init() < 0) {
1538 PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n");
1539 return -1;
1540 }
1541#endif
1542
1543 printk("IN INIT FUNCTION\n");
Arnd Bergmann691f1a22015-05-29 22:52:15 +02001544 printk("*** WILC1000 driver VERSION=[10.2] FW_VER=[10.2] ***\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001545
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001546#ifdef WILC_SDIO
1547 {
1548 int ret;
1549
1550 ret = sdio_register_driver(&wilc_bus);
Kim, Leofc4b95d2015-07-28 17:47:37 +09001551 if (ret < 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001552 PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001553
1554 return ret;
1555 }
1556#else
1557 PRINT_D(INIT_DBG, "Initializing netdev\n");
Glen Lee702c0e52015-10-27 18:20:14 +09001558 if (wilc_netdev_init(&wilc))
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001559 PRINT_ER("Couldn't initialize netdev\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001560 return 0;
1561#endif
1562}
1563late_initcall(init_wilc_driver);
1564
1565static void __exit exit_wilc_driver(void)
1566{
Chaehyun Limc2eda352015-10-02 16:41:13 +09001567#ifndef WILC_SDIO
Geliang Tang0c07f8c2015-10-18 23:31:11 +08001568 PRINT_D(INIT_DBG, "SPI unregister...\n");
Chaehyun Limc2eda352015-10-02 16:41:13 +09001569 spi_unregister_driver(&wilc_bus);
1570#else
Geliang Tang0c07f8c2015-10-18 23:31:11 +08001571 PRINT_D(INIT_DBG, "SDIO unregister...\n");
Chaehyun Limc2eda352015-10-02 16:41:13 +09001572 sdio_unregister_driver(&wilc_bus);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001573#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001574}
1575module_exit(exit_wilc_driver);
1576
1577MODULE_LICENSE("GPL");