Commit 9bc061e8 authored by Ajay Singh's avatar Ajay Singh Committed by Greg Kroah-Hartman

staging: wilc1000: added support to dynamically add/remove interfaces

Removed the use of two hardcoded interfaces and added support to
add/remove the network interfaces dynamically.
Now the driver will have single default interface with name 'wlan0' and
later other interface can be added from user space application e.g
using 'iw add' command.
Also taken care to maintain 'wilc_vif' as part of 'net_device'
private data and 'wilc' struct as 'wiphy' private data.
Signed-off-by: default avatarAjay Singh <ajay.kathat@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6419f818
...@@ -233,6 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, ...@@ -233,6 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
strncpy(wl->monitor_dev->name, name, IFNAMSIZ); strncpy(wl->monitor_dev->name, name, IFNAMSIZ);
wl->monitor_dev->name[IFNAMSIZ - 1] = 0; wl->monitor_dev->name[IFNAMSIZ - 1] = 0;
wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops; wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
wl->monitor_dev->needs_free_netdev = true;
if (register_netdevice(wl->monitor_dev)) { if (register_netdevice(wl->monitor_dev)) {
netdev_err(real_dev, "register_netdevice failed\n"); netdev_err(real_dev, "register_netdevice failed\n");
...@@ -247,12 +248,14 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, ...@@ -247,12 +248,14 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
return wl->monitor_dev; return wl->monitor_dev;
} }
void wilc_wfi_deinit_mon_interface(struct wilc *wl) void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
{ {
if (!wl->monitor_dev) if (!wl->monitor_dev)
return; return;
if (rtnl_locked)
unregister_netdevice(wl->monitor_dev);
else
unregister_netdev(wl->monitor_dev); unregister_netdev(wl->monitor_dev);
free_netdev(wl->monitor_dev);
wl->monitor_dev = NULL; wl->monitor_dev = NULL;
} }
...@@ -97,22 +97,29 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header) ...@@ -97,22 +97,29 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
{ {
u8 *bssid, *bssid1; u8 *bssid, *bssid1;
int i = 0; int i = 0;
struct net_device *ndev = NULL;
bssid = mac_header + 10; bssid = mac_header + 10;
bssid1 = mac_header + 4; bssid1 = mac_header + 4;
mutex_lock(&wilc->vif_mutex);
for (i = 0; i < wilc->vif_num; i++) { for (i = 0; i < wilc->vif_num; i++) {
if (wilc->vif[i]->mode == WILC_STATION_MODE) if (wilc->vif[i]->mode == WILC_STATION_MODE)
if (ether_addr_equal_unaligned(bssid, if (ether_addr_equal_unaligned(bssid,
wilc->vif[i]->bssid)) wilc->vif[i]->bssid)) {
return wilc->vif[i]->ndev; ndev = wilc->vif[i]->ndev;
goto out;
}
if (wilc->vif[i]->mode == WILC_AP_MODE) if (wilc->vif[i]->mode == WILC_AP_MODE)
if (ether_addr_equal_unaligned(bssid1, if (ether_addr_equal_unaligned(bssid1,
wilc->vif[i]->bssid)) wilc->vif[i]->bssid)) {
return wilc->vif[i]->ndev; ndev = wilc->vif[i]->ndev;
goto out;
} }
}
return NULL; out:
mutex_unlock(&wilc->vif_mutex);
return ndev;
} }
void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode) void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
...@@ -143,9 +150,7 @@ static int wilc_txq_task(void *vp) ...@@ -143,9 +150,7 @@ static int wilc_txq_task(void *vp)
{ {
int ret; int ret;
u32 txq_count; u32 txq_count;
struct net_device *dev = vp; struct wilc *wl = vp;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc;
complete(&wl->txq_thread_started); complete(&wl->txq_thread_started);
while (1) { while (1) {
...@@ -159,14 +164,18 @@ static int wilc_txq_task(void *vp) ...@@ -159,14 +164,18 @@ static int wilc_txq_task(void *vp)
break; break;
} }
do { do {
ret = wilc_wlan_handle_txq(dev, &txq_count); ret = wilc_wlan_handle_txq(wl, &txq_count);
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) { if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
if (wl->vif[0]->mac_opened && int i;
netif_queue_stopped(wl->vif[0]->ndev)) struct wilc_vif *ifc;
netif_wake_queue(wl->vif[0]->ndev);
if (wl->vif[1]->mac_opened && mutex_lock(&wl->vif_mutex);
netif_queue_stopped(wl->vif[1]->ndev)) for (i = 0; i < wl->vif_num; i++) {
netif_wake_queue(wl->vif[1]->ndev); ifc = wl->vif[i];
if (ifc->mac_opened && ifc->ndev)
netif_wake_queue(ifc->ndev);
}
mutex_unlock(&wl->vif_mutex);
} }
} while (ret == -ENOBUFS && !wl->close); } while (ret == -ENOBUFS && !wl->close);
} }
...@@ -245,14 +254,13 @@ static int wilc1000_firmware_download(struct net_device *dev) ...@@ -245,14 +254,13 @@ static int wilc1000_firmware_download(struct net_device *dev)
static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif) static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
{ {
struct wilc_priv *priv; struct wilc_priv *priv = &vif->priv;
struct host_if_drv *hif_drv; struct host_if_drv *hif_drv;
u8 b; u8 b;
u16 hw; u16 hw;
u32 w; u32 w;
netdev_dbg(dev, "Start configuring Firmware\n"); netdev_dbg(dev, "Start configuring Firmware\n");
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
hif_drv = (struct host_if_drv *)priv->hif_drv; hif_drv = (struct host_if_drv *)priv->hif_drv;
netdev_dbg(dev, "Host = %p\n", hif_drv); netdev_dbg(dev, "Host = %p\n", hif_drv);
...@@ -424,6 +432,7 @@ static void wlan_deinit_locks(struct net_device *dev) ...@@ -424,6 +432,7 @@ static void wlan_deinit_locks(struct net_device *dev)
mutex_destroy(&wilc->rxq_cs); mutex_destroy(&wilc->rxq_cs);
mutex_destroy(&wilc->cfg_cmd_lock); mutex_destroy(&wilc->cfg_cmd_lock);
mutex_destroy(&wilc->txq_add_to_head_cs); mutex_destroy(&wilc->txq_add_to_head_cs);
mutex_destroy(&wilc->vif_mutex);
} }
static void wlan_deinitialize_threads(struct net_device *dev) static void wlan_deinitialize_threads(struct net_device *dev)
...@@ -477,31 +486,12 @@ static void wilc_wlan_deinitialize(struct net_device *dev) ...@@ -477,31 +486,12 @@ static void wilc_wlan_deinitialize(struct net_device *dev)
} }
} }
static void wlan_init_locks(struct net_device *dev)
{
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc;
mutex_init(&wl->hif_cs);
mutex_init(&wl->rxq_cs);
mutex_init(&wl->cfg_cmd_lock);
spin_lock_init(&wl->txq_spinlock);
mutex_init(&wl->txq_add_to_head_cs);
init_completion(&wl->txq_event);
init_completion(&wl->cfg_event);
init_completion(&wl->sync_event);
init_completion(&wl->txq_thread_started);
}
static int wlan_initialize_threads(struct net_device *dev) static int wlan_initialize_threads(struct net_device *dev)
{ {
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc; struct wilc *wilc = vif->wilc;
wilc->txq_thread = kthread_run(wilc_txq_task, (void *)dev, wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
"K_TXQ_TASK"); "K_TXQ_TASK");
if (IS_ERR(wilc->txq_thread)) { if (IS_ERR(wilc->txq_thread)) {
netdev_err(dev, "couldn't create TXQ thread\n"); netdev_err(dev, "couldn't create TXQ thread\n");
...@@ -513,6 +503,12 @@ static int wlan_initialize_threads(struct net_device *dev) ...@@ -513,6 +503,12 @@ static int wlan_initialize_threads(struct net_device *dev)
return 0; return 0;
} }
static int dev_state_ev_handler(struct notifier_block *this,
unsigned long event, void *ptr);
static struct notifier_block g_dev_notifier = {
.notifier_call = dev_state_ev_handler
};
static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
{ {
int ret = 0; int ret = 0;
...@@ -522,13 +518,9 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ...@@ -522,13 +518,9 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
wl->mac_status = WILC_MAC_STATUS_INIT; wl->mac_status = WILC_MAC_STATUS_INIT;
wl->close = 0; wl->close = 0;
wlan_init_locks(dev);
ret = wilc_wlan_init(dev); ret = wilc_wlan_init(dev);
if (ret < 0) { if (ret < 0)
ret = -EIO; return -EIO;
goto fail_locks;
}
ret = wlan_initialize_threads(dev); ret = wlan_initialize_threads(dev);
if (ret < 0) { if (ret < 0) {
...@@ -582,7 +574,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ...@@ -582,7 +574,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
ret = -EIO; ret = -EIO;
goto fail_fw_start; goto fail_fw_start;
} }
register_inetaddr_notifier(&g_dev_notifier);
wl->initialized = true; wl->initialized = true;
return 0; return 0;
...@@ -600,8 +592,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ...@@ -600,8 +592,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
wlan_deinitialize_threads(dev); wlan_deinitialize_threads(dev);
fail_wilc_wlan: fail_wilc_wlan:
wilc_wlan_cleanup(dev); wilc_wlan_cleanup(dev);
fail_locks:
wlan_deinit_locks(dev);
netdev_err(dev, "WLAN initialization FAILED\n"); netdev_err(dev, "WLAN initialization FAILED\n");
} else { } else {
netdev_dbg(dev, "wilc1000 already initialized\n"); netdev_dbg(dev, "wilc1000 already initialized\n");
...@@ -758,16 +748,19 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -758,16 +748,19 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
vif->netstats.tx_packets++; vif->netstats.tx_packets++;
vif->netstats.tx_bytes += tx_data->size; vif->netstats.tx_bytes += tx_data->size;
tx_data->bssid = wilc->vif[vif->idx]->bssid;
queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
tx_data->buff, tx_data->size, tx_data->buff, tx_data->size,
wilc_tx_complete); wilc_tx_complete);
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) { if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
if (wilc->vif[0]->mac_opened) int i;
netif_stop_queue(wilc->vif[0]->ndev);
if (wilc->vif[1]->mac_opened) mutex_lock(&wilc->vif_mutex);
netif_stop_queue(wilc->vif[1]->ndev); for (i = 0; i < wilc->vif_num; i++) {
if (wilc->vif[i]->mac_opened)
netif_stop_queue(wilc->vif[i]->ndev);
}
mutex_unlock(&wilc->vif_mutex);
} }
return 0; return 0;
...@@ -794,6 +787,7 @@ static int wilc_mac_close(struct net_device *ndev) ...@@ -794,6 +787,7 @@ static int wilc_mac_close(struct net_device *ndev)
if (wl->open_ifcs == 0) { if (wl->open_ifcs == 0) {
netdev_dbg(ndev, "Deinitializing wilc1000\n"); netdev_dbg(ndev, "Deinitializing wilc1000\n");
wl->close = 1; wl->close = 1;
unregister_inetaddr_notifier(&g_dev_notifier);
wilc_wlan_deinitialize(ndev); wilc_wlan_deinitialize(ndev);
} }
...@@ -848,18 +842,23 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) ...@@ -848,18 +842,23 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
int i = 0; int i = 0;
struct wilc_vif *vif; struct wilc_vif *vif;
mutex_lock(&wilc->vif_mutex);
for (i = 0; i < wilc->vif_num; i++) { for (i = 0; i < wilc->vif_num; i++) {
u16 type = le16_to_cpup((__le16 *)buff);
vif = netdev_priv(wilc->vif[i]->ndev); vif = netdev_priv(wilc->vif[i]->ndev);
if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
(type == vif->frame_reg[1].type && vif->frame_reg[1].reg)) {
wilc_wfi_p2p_rx(vif, buff, size);
break;
}
if (vif->monitor_flag) { if (vif->monitor_flag) {
wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size); wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
return; break;
} }
} }
mutex_unlock(&wilc->vif_mutex);
vif = netdev_priv(wilc->vif[1]->ndev);
if ((buff[0] == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
(buff[0] == vif->frame_reg[1].type && vif->frame_reg[1].reg))
wilc_wfi_p2p_rx(wilc->vif[1]->ndev, buff, size);
} }
static const struct net_device_ops wilc_netdev_ops = { static const struct net_device_ops wilc_netdev_ops = {
...@@ -890,14 +889,10 @@ static int dev_state_ev_handler(struct notifier_block *this, ...@@ -890,14 +889,10 @@ static int dev_state_ev_handler(struct notifier_block *this,
if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
return NOTIFY_DONE; return NOTIFY_DONE;
priv = wiphy_priv(dev->ieee80211_ptr->wiphy); vif = netdev_priv(dev);
if (!priv) priv = &vif->priv;
return NOTIFY_DONE;
hif_drv = (struct host_if_drv *)priv->hif_drv; hif_drv = (struct host_if_drv *)priv->hif_drv;
vif = netdev_priv(dev);
if (!vif || !hif_drv)
return NOTIFY_DONE;
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_UP:
...@@ -932,10 +927,6 @@ static int dev_state_ev_handler(struct notifier_block *this, ...@@ -932,10 +927,6 @@ static int dev_state_ev_handler(struct notifier_block *this,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block g_dev_notifier = {
.notifier_call = dev_state_ev_handler
};
void wilc_netdev_cleanup(struct wilc *wilc) void wilc_netdev_cleanup(struct wilc *wilc)
{ {
int i; int i;
...@@ -943,136 +934,72 @@ void wilc_netdev_cleanup(struct wilc *wilc) ...@@ -943,136 +934,72 @@ void wilc_netdev_cleanup(struct wilc *wilc)
if (!wilc) if (!wilc)
return; return;
if (wilc->vif[0]->ndev || wilc->vif[1]->ndev)
unregister_inetaddr_notifier(&g_dev_notifier);
if (wilc->firmware) { if (wilc->firmware) {
release_firmware(wilc->firmware); release_firmware(wilc->firmware);
wilc->firmware = NULL; wilc->firmware = NULL;
} }
for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) { for (i = 0; i < wilc->vif_num; i++) {
if (wilc->vif[i] && wilc->vif[i]->ndev) { if (wilc->vif[i] && wilc->vif[i]->ndev)
unregister_netdev(wilc->vif[i]->ndev); unregister_netdev(wilc->vif[i]->ndev);
wilc_free_wiphy(wilc->vif[i]->ndev);
free_netdev(wilc->vif[i]->ndev);
}
} }
wilc_wfi_deinit_mon_interface(wilc); wilc_wfi_deinit_mon_interface(wilc, false);
flush_workqueue(wilc->hif_workqueue); flush_workqueue(wilc->hif_workqueue);
destroy_workqueue(wilc->hif_workqueue); destroy_workqueue(wilc->hif_workqueue);
wilc_wlan_cfg_deinit(wilc); wilc_wlan_cfg_deinit(wilc);
kfree(wilc->bus_data); kfree(wilc->bus_data);
kfree(wilc); wiphy_unregister(wilc->wiphy);
wiphy_free(wilc->wiphy);
} }
EXPORT_SYMBOL_GPL(wilc_netdev_cleanup); EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
const struct wilc_hif_func *ops) int vif_type, enum nl80211_iftype type,
bool rtnl_locked)
{ {
int i, ret;
struct wilc_vif *vif;
struct net_device *ndev; struct net_device *ndev;
struct wilc *wl; struct wilc_vif *vif;
int ret;
wl = kzalloc(sizeof(*wl), GFP_KERNEL);
if (!wl)
return -ENOMEM;
ret = wilc_wlan_cfg_init(wl);
if (ret)
goto free_wl;
*wilc = wl;
wl->io_type = io_type;
wl->hif_func = ops;
wl->enable_ps = true;
wl->chip_ps_state = WILC_CHIP_WAKEDUP;
INIT_LIST_HEAD(&wl->txq_head.list);
INIT_LIST_HEAD(&wl->rxq_head.list);
wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
if (!wl->hif_workqueue) {
ret = -ENOMEM;
goto free_cfg;
}
register_inetaddr_notifier(&g_dev_notifier);
for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
struct wireless_dev *wdev;
ndev = alloc_etherdev(sizeof(struct wilc_vif)); ndev = alloc_etherdev(sizeof(*vif));
if (!ndev) { if (!ndev)
ret = -ENOMEM; return ERR_PTR(-ENOMEM);
goto free_ndev;
}
vif = netdev_priv(ndev); vif = netdev_priv(ndev);
ndev->ieee80211_ptr = &vif->priv.wdev;
if (i == 0) { strcpy(ndev->name, name);
strcpy(ndev->name, "wlan%d"); vif->wilc = wl;
vif->ifc_id = 1;
} else {
strcpy(ndev->name, "p2p%d");
vif->ifc_id = 0;
}
vif->wilc = *wilc;
vif->ndev = ndev; vif->ndev = ndev;
wl->vif[i] = vif; ndev->ml_priv = vif;
wl->vif_num = i + 1;
vif->idx = i;
ndev->netdev_ops = &wilc_netdev_ops; ndev->netdev_ops = &wilc_netdev_ops;
wdev = wilc_create_wiphy(ndev, dev); SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
if (!wdev) {
netdev_err(ndev, "Can't register WILC Wiphy\n");
ret = -ENOMEM;
goto free_ndev;
}
SET_NETDEV_DEV(ndev, dev);
vif->ndev->ieee80211_ptr = wdev; vif->priv.wdev.wiphy = wl->wiphy;
vif->ndev->ml_priv = vif; vif->priv.wdev.netdev = ndev;
wdev->netdev = vif->ndev; vif->priv.wdev.iftype = type;
vif->netstats.rx_packets = 0; vif->priv.dev = ndev;
vif->netstats.tx_packets = 0;
vif->netstats.rx_bytes = 0;
vif->netstats.tx_bytes = 0;
if (rtnl_locked)
ret = register_netdevice(ndev);
else
ret = register_netdev(ndev); ret = register_netdev(ndev);
if (ret)
goto free_ndev;
vif->iftype = WILC_STATION_MODE; if (ret) {
vif->mac_opened = 0; free_netdev(ndev);
return ERR_PTR(-EFAULT);
} }
return 0; ndev->needs_free_netdev = true;
vif->iftype = vif_type;
free_ndev: vif->wilc->vif[wl->vif_num] = vif;
for (; i >= 0; i--) { vif->ifc_id = wl->vif_num;
if (wl->vif[i]) { vif->idx = wl->vif_num;
if (wl->vif[i]->iftype == WILC_STATION_MODE) wl->vif_num += 1;
unregister_netdev(wl->vif[i]->ndev); vif->mac_opened = 0;
return vif;
if (wl->vif[i]->ndev) {
wilc_free_wiphy(wl->vif[i]->ndev);
free_netdev(wl->vif[i]->ndev);
}
}
}
unregister_inetaddr_notifier(&g_dev_notifier);
destroy_workqueue(wl->hif_workqueue);
free_cfg:
wilc_wlan_cfg_deinit(wl);
free_wl:
kfree(wl);
return ret;
} }
EXPORT_SYMBOL_GPL(wilc_netdev_init);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include "wilc_wfi_netdevice.h" #include "wilc_wfi_netdevice.h"
#include "wilc_wfi_cfgoperations.h"
#define SDIO_MODALIAS "wilc1000_sdio" #define SDIO_MODALIAS "wilc1000_sdio"
...@@ -139,11 +140,9 @@ static int wilc_sdio_probe(struct sdio_func *func, ...@@ -139,11 +140,9 @@ static int wilc_sdio_probe(struct sdio_func *func,
} }
} }
dev_dbg(&func->dev, "Initializing netdev\n"); ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
ret = wilc_netdev_init(&wilc, &func->dev, WILC_HIF_SDIO,
&wilc_hif_sdio); &wilc_hif_sdio);
if (ret) { if (ret) {
dev_err(&func->dev, "Couldn't initialize netdev\n");
kfree(sdio_priv); kfree(sdio_priv);
return ret; return ret;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include "wilc_wfi_netdevice.h" #include "wilc_wfi_netdevice.h"
#include "wilc_wfi_cfgoperations.h"
struct wilc_spi { struct wilc_spi {
int crc_off; int crc_off;
...@@ -120,7 +121,7 @@ static int wilc_bus_probe(struct spi_device *spi) ...@@ -120,7 +121,7 @@ static int wilc_bus_probe(struct spi_device *spi)
dev_err(&spi->dev, "failed to get the irq gpio\n"); dev_err(&spi->dev, "failed to get the irq gpio\n");
} }
ret = wilc_netdev_init(&wilc, NULL, WILC_HIF_SPI, &wilc_hif_spi); ret = wilc_cfg80211_init(&wilc, &spi->dev, WILC_HIF_SPI, &wilc_hif_spi);
if (ret) { if (ret) {
kfree(spi_priv); kfree(spi_priv);
return ret; return ret;
......
...@@ -183,48 +183,67 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, ...@@ -183,48 +183,67 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
eth_zero_addr(priv->associated_bss); eth_zero_addr(priv->associated_bss);
wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);
if (vif->iftype != WILC_CLIENT_MODE) if (vif->iftype != WILC_CLIENT_MODE) {
wl->sta_ch = WILC_INVALID_CHANNEL; wl->sta_ch = WILC_INVALID_CHANNEL;
} else {
if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev) if (wfi_drv->ifc_up)
reason = 3; reason = 3;
else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev) else
reason = 1; reason = 1;
}
cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL); cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL);
} }
} }
static struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
{
int i;
for (i = 0; i < wl->vif_num; i++)
if (wl->vif[i])
return wl->vif[i];
return ERR_PTR(-EINVAL);
}
static int set_channel(struct wiphy *wiphy, static int set_channel(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef) struct cfg80211_chan_def *chandef)
{ {
u32 channelnum = 0; struct wilc *wl = wiphy_priv(wiphy);
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif;
struct wilc_vif *vif = netdev_priv(priv->dev); u32 channelnum;
int result = 0; int result;
mutex_lock(&wl->vif_mutex);
vif = wilc_get_wl_to_vif(wl);
if (IS_ERR(vif)) {
mutex_unlock(&wl->vif_mutex);
return PTR_ERR(vif);
}
channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq); channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
vif->wilc->op_ch = channelnum; wl->op_ch = channelnum;
result = wilc_set_mac_chnl_num(vif, channelnum); result = wilc_set_mac_chnl_num(vif, channelnum);
if (result)
netdev_err(vif->ndev, "Error in setting channel\n");
if (result != 0) mutex_unlock(&wl->vif_mutex);
netdev_err(priv->dev, "Error in setting channel\n");
return result; return result;
} }
static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(request->wdev->netdev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
u32 i; u32 i;
int ret = 0; int ret = 0;
u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH]; u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];
u8 scan_type; u8 scan_type;
if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) { if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) {
netdev_err(priv->dev, "Requested scanned channels over\n"); netdev_err(vif->ndev, "Requested scanned channels over\n");
return -EINVAL; return -EINVAL;
} }
...@@ -256,8 +275,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) ...@@ -256,8 +275,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
static int connect(struct wiphy *wiphy, struct net_device *dev, static int connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme) struct cfg80211_connect_params *sme)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
struct host_if_drv *wfi_drv = priv->hif_drv; struct host_if_drv *wfi_drv = priv->hif_drv;
int ret; int ret;
u32 i; u32 i;
...@@ -410,8 +429,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, ...@@ -410,8 +429,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
static int disconnect(struct wiphy *wiphy, struct net_device *dev, static int disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code) u16 reason_code)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
struct wilc *wilc = vif->wilc; struct wilc *wilc = vif->wilc;
int ret; int ret;
...@@ -501,17 +520,17 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, ...@@ -501,17 +520,17 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
{ {
int ret = 0, keylen = params->key_len; int ret = 0, keylen = params->key_len;
struct wilc_priv *priv = wiphy_priv(wiphy);
const u8 *rx_mic = NULL; const u8 *rx_mic = NULL;
const u8 *tx_mic = NULL; const u8 *tx_mic = NULL;
u8 mode = WILC_FW_SEC_NO; u8 mode = WILC_FW_SEC_NO;
u8 op_mode; u8 op_mode;
struct wilc_vif *vif = netdev_priv(netdev); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_priv *priv = &vif->priv;
switch (params->cipher) { switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
if (priv->wdev->iftype == NL80211_IFTYPE_AP) { if (priv->wdev.iftype == NL80211_IFTYPE_AP) {
wilc_wfi_cfg_copy_wep_info(priv, key_index, params); wilc_wfi_cfg_copy_wep_info(priv, key_index, params);
if (params->cipher == WLAN_CIPHER_SUITE_WEP40) if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
...@@ -538,8 +557,8 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, ...@@ -538,8 +557,8 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
if (priv->wdev->iftype == NL80211_IFTYPE_AP || if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) { priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
struct wilc_wfi_key *key; struct wilc_wfi_key *key;
ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index); ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index);
...@@ -611,9 +630,9 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, ...@@ -611,9 +630,9 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
bool pairwise, bool pairwise,
const u8 *mac_addr) const u8 *mac_addr)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(netdev); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc *wl = vif->wilc; struct wilc_priv *priv = &vif->priv;
if (netdev == wl->vif[0]->ndev) { if (netdev == wl->vif[0]->ndev) {
if (priv->wilc_gtk[key_index]) { if (priv->wilc_gtk[key_index]) {
...@@ -650,7 +669,8 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, ...@@ -650,7 +669,8 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
bool pairwise, const u8 *mac_addr, void *cookie, bool pairwise, const u8 *mac_addr, void *cookie,
void (*callback)(void *cookie, struct key_params *)) void (*callback)(void *cookie, struct key_params *))
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_priv *priv = &vif->priv;
struct key_params key_params; struct key_params key_params;
if (!pairwise) { if (!pairwise) {
...@@ -675,8 +695,7 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, ...@@ -675,8 +695,7 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool unicast, bool multicast) u8 key_index, bool unicast, bool multicast)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_vif *vif = netdev_priv(priv->dev);
wilc_set_wep_default_keyid(vif, key_index); wilc_set_wep_default_keyid(vif, key_index);
...@@ -686,8 +705,8 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, ...@@ -686,8 +705,8 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
static int get_station(struct wiphy *wiphy, struct net_device *dev, static int get_station(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac, struct station_info *sinfo) const u8 *mac, struct station_info *sinfo)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_priv *priv = &vif->priv;
u32 i = 0; u32 i = 0;
u32 associatedsta = ~0; u32 associatedsta = ~0;
u32 inactive_time = 0; u32 inactive_time = 0;
...@@ -743,13 +762,35 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev, ...@@ -743,13 +762,35 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev,
return 0; return 0;
} }
struct wilc_vif *wilc_get_interface(struct wilc *wl)
{
int i;
struct wilc_vif *vif = NULL;
mutex_lock(&wl->vif_mutex);
for (i = 0; i < wl->vif_num; i++) {
if (wl->vif[i]) {
vif = wl->vif[i];
break;
}
}
mutex_unlock(&wl->vif_mutex);
return vif;
}
static int set_wiphy_params(struct wiphy *wiphy, u32 changed) static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
{ {
int ret; int ret;
struct cfg_param_attr cfg_param_val; struct cfg_param_attr cfg_param_val;
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_vif *vif;
struct wilc_priv *priv;
vif = wilc_get_interface(wl);
if (!vif)
return -EINVAL;
priv = &vif->priv;
cfg_param_val.flag = 0; cfg_param_val.flag = 0;
if (changed & WIPHY_PARAM_RETRY_SHORT) { if (changed & WIPHY_PARAM_RETRY_SHORT) {
...@@ -804,8 +845,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed) ...@@ -804,8 +845,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev, static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_pmksa *pmksa) struct cfg80211_pmksa *pmksa)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
u32 i; u32 i;
int ret = 0; int ret = 0;
u8 flag = 0; u8 flag = 0;
...@@ -840,7 +881,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev, ...@@ -840,7 +881,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
{ {
u32 i; u32 i;
int ret = 0; int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(netdev);
struct wilc_priv *priv = &vif->priv;
for (i = 0; i < priv->pmkid_list.numpmkid; i++) { for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
...@@ -870,9 +912,9 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev, ...@@ -870,9 +912,9 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(netdev);
memset(&priv->pmkid_list, 0, sizeof(struct wilc_pmkid_attr)); memset(&vif->priv.pmkid_list, 0, sizeof(struct wilc_pmkid_attr));
return 0; return 0;
} }
...@@ -987,12 +1029,11 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff, ...@@ -987,12 +1029,11 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
} }
} }
void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
{ {
struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
struct host_if_drv *wfi_drv = priv->hif_drv;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc; struct wilc *wl = vif->wilc;
struct wilc_priv *priv = &vif->priv;
struct host_if_drv *wfi_drv = priv->hif_drv;
u32 header, pkt_offset; u32 header, pkt_offset;
s32 freq; s32 freq;
__le16 fc; __le16 fc;
...@@ -1008,8 +1049,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) ...@@ -1008,8 +1049,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
pkt_offset & IS_MGMT_STATUS_SUCCES) pkt_offset & IS_MGMT_STATUS_SUCCES)
ack = true; ack = true;
cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size, cfg80211_mgmt_tx_status(&priv->wdev, priv->tx_cookie, buff,
ack, GFP_KERNEL); size, ack, GFP_KERNEL);
return; return;
} }
...@@ -1017,13 +1058,13 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) ...@@ -1017,13 +1058,13 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
fc = ((struct ieee80211_hdr *)buff)->frame_control; fc = ((struct ieee80211_hdr *)buff)->frame_control;
if (!ieee80211_is_action(fc)) { if (!ieee80211_is_action(fc)) {
cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0); cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
return; return;
} }
if (priv->cfg_scanning && if (priv->cfg_scanning &&
time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) { time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {
netdev_dbg(dev, "Receiving action wrong ch\n"); netdev_dbg(vif->ndev, "Receiving action wrong ch\n");
return; return;
} }
if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
...@@ -1046,14 +1087,14 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) ...@@ -1046,14 +1087,14 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
break; break;
default: default:
netdev_dbg(dev, netdev_dbg(vif->ndev,
"%s: Not handled action frame type:%x\n", "%s: Not handled action frame type:%x\n",
__func__, buff[ACTION_SUBTYPE_ID]); __func__, buff[ACTION_SUBTYPE_ID]);
break; break;
} }
} }
cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0); cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
} }
static void wilc_wfi_mgmt_tx_complete(void *priv, int status) static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
...@@ -1066,7 +1107,8 @@ static void wilc_wfi_mgmt_tx_complete(void *priv, int status) ...@@ -1066,7 +1107,8 @@ static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie) static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
{ {
struct wilc_priv *priv = data; struct wilc_vif *vif = data;
struct wilc_priv *priv = &vif->priv;
struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params; struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;
if (cookie != params->listen_cookie) if (cookie != params->listen_cookie)
...@@ -1074,7 +1116,7 @@ static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie) ...@@ -1074,7 +1116,7 @@ static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
priv->p2p_listen_state = false; priv->p2p_listen_state = false;
cfg80211_remain_on_channel_expired(priv->wdev, params->listen_cookie, cfg80211_remain_on_channel_expired(&priv->wdev, params->listen_cookie,
params->listen_ch, GFP_KERNEL); params->listen_ch, GFP_KERNEL);
} }
...@@ -1084,8 +1126,8 @@ static int remain_on_channel(struct wiphy *wiphy, ...@@ -1084,8 +1126,8 @@ static int remain_on_channel(struct wiphy *wiphy,
unsigned int duration, u64 *cookie) unsigned int duration, u64 *cookie)
{ {
int ret = 0; int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
u64 id; u64 id;
if (wdev->iftype == NL80211_IFTYPE_AP) { if (wdev->iftype == NL80211_IFTYPE_AP) {
...@@ -1099,7 +1141,7 @@ static int remain_on_channel(struct wiphy *wiphy, ...@@ -1099,7 +1141,7 @@ static int remain_on_channel(struct wiphy *wiphy,
ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value, ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
wilc_wfi_remain_on_channel_expired, wilc_wfi_remain_on_channel_expired,
(void *)priv); (void *)vif);
if (ret) if (ret)
return ret; return ret;
...@@ -1122,8 +1164,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy, ...@@ -1122,8 +1164,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
u64 cookie) u64 cookie)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
if (cookie != priv->remain_on_ch_params.listen_cookie) if (cookie != priv->remain_on_ch_params.listen_cookie)
return -ENOENT; return -ENOENT;
...@@ -1193,9 +1235,9 @@ static int mgmt_tx(struct wiphy *wiphy, ...@@ -1193,9 +1235,9 @@ static int mgmt_tx(struct wiphy *wiphy,
size_t len = params->len; size_t len = params->len;
const struct ieee80211_mgmt *mgmt; const struct ieee80211_mgmt *mgmt;
struct wilc_p2p_mgmt_data *mgmt_tx; struct wilc_p2p_mgmt_data *mgmt_tx;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct host_if_drv *wfi_drv = priv->hif_drv;
struct wilc_vif *vif = netdev_priv(wdev->netdev); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_priv *priv = &vif->priv;
struct host_if_drv *wfi_drv = priv->hif_drv;
u32 buf_len = len + sizeof(p2p_vendor_spec) + u32 buf_len = len + sizeof(p2p_vendor_spec) +
sizeof(priv->p2p.local_random); sizeof(priv->p2p.local_random);
int ret = 0; int ret = 0;
...@@ -1279,7 +1321,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, ...@@ -1279,7 +1321,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
u64 cookie) u64 cookie)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_priv *priv = &vif->priv;
struct host_if_drv *wfi_drv = priv->hif_drv; struct host_if_drv *wfi_drv = priv->hif_drv;
wfi_drv->p2p_timeout = jiffies; wfi_drv->p2p_timeout = jiffies;
...@@ -1289,7 +1332,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, ...@@ -1289,7 +1332,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
params = &priv->remain_on_ch_params; params = &priv->remain_on_ch_params;
cfg80211_remain_on_channel_expired(priv->wdev, cfg80211_remain_on_channel_expired(wdev,
params->listen_cookie, params->listen_cookie,
params->listen_ch, params->listen_ch,
GFP_KERNEL); GFP_KERNEL);
...@@ -1301,9 +1344,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, ...@@ -1301,9 +1344,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
u16 frame_type, bool reg) u16 frame_type, bool reg)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->wdev->netdev); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc *wl = vif->wilc;
if (!frame_type) if (!frame_type)
return; return;
...@@ -1337,8 +1379,7 @@ static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev, ...@@ -1337,8 +1379,7 @@ static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
static int dump_station(struct wiphy *wiphy, struct net_device *dev, static int dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo) int idx, u8 *mac, struct station_info *sinfo)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev);
int ret; int ret;
if (idx != 0) if (idx != 0)
...@@ -1350,15 +1391,15 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -1350,15 +1391,15 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev,
if (ret) if (ret)
return ret; return ret;
memcpy(mac, priv->associated_bss, ETH_ALEN); memcpy(mac, vif->priv.associated_bss, ETH_ALEN);
return 0; return 0;
} }
static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
bool enabled, int timeout) bool enabled, int timeout)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
if (!priv->hif_drv) if (!priv->hif_drv)
return -EIO; return -EIO;
...@@ -1373,9 +1414,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, ...@@ -1373,9 +1414,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
enum nl80211_iftype type, enum nl80211_iftype type,
struct vif_params *params) struct vif_params *params)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc; struct wilc_priv *priv = &vif->priv;
priv->p2p.local_random = 0x01; priv->p2p.local_random = 0x01;
priv->p2p.recv_random = 0x00; priv->p2p.recv_random = 0x00;
...@@ -1387,8 +1428,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, ...@@ -1387,8 +1428,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
vif->connecting = false; vif->connecting = false;
dev->ieee80211_ptr->iftype = type; dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type; priv->wdev.iftype = type;
vif->monitor_flag = 0; vif->monitor_flag = 0;
if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)
wilc_wfi_deinit_mon_interface(wl, true);
vif->iftype = WILC_STATION_MODE; vif->iftype = WILC_STATION_MODE;
wilc_set_operation_mode(vif, WILC_STATION_MODE); wilc_set_operation_mode(vif, WILC_STATION_MODE);
...@@ -1402,7 +1445,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, ...@@ -1402,7 +1445,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
vif->connecting = false; vif->connecting = false;
dev->ieee80211_ptr->iftype = type; dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type; priv->wdev.iftype = type;
vif->monitor_flag = 0; vif->monitor_flag = 0;
vif->iftype = WILC_CLIENT_MODE; vif->iftype = WILC_CLIENT_MODE;
wilc_set_operation_mode(vif, WILC_STATION_MODE); wilc_set_operation_mode(vif, WILC_STATION_MODE);
...@@ -1414,7 +1457,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, ...@@ -1414,7 +1457,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
wl->enable_ps = false; wl->enable_ps = false;
dev->ieee80211_ptr->iftype = type; dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type; priv->wdev.iftype = type;
vif->iftype = WILC_AP_MODE; vif->iftype = WILC_AP_MODE;
if (wl->initialized) { if (wl->initialized) {
...@@ -1431,7 +1474,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, ...@@ -1431,7 +1474,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)); jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS));
wilc_set_operation_mode(vif, WILC_AP_MODE); wilc_set_operation_mode(vif, WILC_AP_MODE);
dev->ieee80211_ptr->iftype = type; dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type; priv->wdev.iftype = type;
vif->iftype = WILC_GO_MODE; vif->iftype = WILC_GO_MODE;
wl->enable_ps = false; wl->enable_ps = false;
...@@ -1450,14 +1493,13 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1450,14 +1493,13 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ap_settings *settings) struct cfg80211_ap_settings *settings)
{ {
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc;
int ret; int ret;
ret = set_channel(wiphy, &settings->chandef); ret = set_channel(wiphy, &settings->chandef);
if (ret != 0) if (ret != 0)
netdev_err(dev, "Error in setting channel\n"); netdev_err(dev, "Error in setting channel\n");
wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, WILC_AP_MODE); wilc_wlan_set_bssid(dev, vif->src_addr, WILC_AP_MODE);
wilc_set_power_mgmt(vif, 0, 0); wilc_set_power_mgmt(vif, 0, 0);
return wilc_add_beacon(vif, settings->beacon_interval, return wilc_add_beacon(vif, settings->beacon_interval,
...@@ -1467,8 +1509,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1467,8 +1509,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
static int change_beacon(struct wiphy *wiphy, struct net_device *dev, static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_beacon_data *beacon) struct cfg80211_beacon_data *beacon)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev);
return wilc_add_beacon(vif, 0, 0, beacon); return wilc_add_beacon(vif, 0, 0, beacon);
} }
...@@ -1476,8 +1517,7 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev, ...@@ -1476,8 +1517,7 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
static int stop_ap(struct wiphy *wiphy, struct net_device *dev) static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
{ {
int ret; int ret;
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_vif *vif = netdev_priv(priv->dev);
wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE); wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);
...@@ -1493,8 +1533,8 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -1493,8 +1533,8 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac, struct station_parameters *params) const u8 *mac, struct station_parameters *params)
{ {
int ret = 0; int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_priv *priv = &vif->priv;
if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) { if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {
memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac, memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac,
...@@ -1513,8 +1553,8 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -1513,8 +1553,8 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev,
{ {
const u8 *mac = params->mac; const u8 *mac = params->mac;
int ret = 0; int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc_priv *priv = &vif->priv;
struct sta_info *info; struct sta_info *info;
if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)) if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE))
...@@ -1545,60 +1585,158 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -1545,60 +1585,158 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
return ret; return ret;
} }
static int wilc_get_vif_from_type(struct wilc *wl, int type)
{
int i;
mutex_lock(&wl->vif_mutex);
for (i = 0; i < wl->vif_num; i++) {
if (wl->vif[i]->iftype == type) {
mutex_unlock(&wl->vif_mutex);
return i;
}
}
mutex_unlock(&wl->vif_mutex);
return -EINVAL;
}
static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
const char *name, const char *name,
unsigned char name_assign_type, unsigned char name_assign_type,
enum nl80211_iftype type, enum nl80211_iftype type,
struct vif_params *params) struct vif_params *params)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->wdev->netdev); struct wilc_vif *vif;
struct net_device *new_ifc; struct wireless_dev *wdev;
int iftype;
int ret;
if (type == NL80211_IFTYPE_MONITOR) { if (type == NL80211_IFTYPE_MONITOR) {
new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name, struct net_device *ndev;
vif->ndev); int ap_index = wilc_get_vif_from_type(wl, WILC_AP_MODE);
if (new_ifc) {
vif = netdev_priv(priv->wdev->netdev); if (ap_index < 0) {
ap_index = wilc_get_vif_from_type(wl, WILC_GO_MODE);
if (ap_index < 0)
goto validate_interface;
}
vif = wl->vif[ap_index];
if (vif->monitor_flag)
goto validate_interface;
ndev = wilc_wfi_init_mon_interface(wl, name, vif->ndev);
if (ndev)
vif->monitor_flag = 1; vif->monitor_flag = 1;
else
return ERR_PTR(-EINVAL);
wdev = &vif->priv.wdev;
return wdev;
}
validate_interface:
mutex_lock(&wl->vif_mutex);
if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {
pr_err("Reached maximum number of interface\n");
ret = -EINVAL;
goto out_err;
}
switch (type) {
case NL80211_IFTYPE_STATION:
iftype = WILC_STATION_MODE;
break;
case NL80211_IFTYPE_AP:
iftype = WILC_AP_MODE;
break;
default:
ret = -EOPNOTSUPP;
goto out_err;
} }
vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);
if (IS_ERR(vif)) {
ret = PTR_ERR(vif);
goto out_err;
} }
return priv->wdev;
mutex_unlock(&wl->vif_mutex);
return &vif->priv.wdev;
out_err:
mutex_unlock(&wl->vif_mutex);
return ERR_PTR(ret);
} }
static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{ {
struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif;
int i;
if (wdev->iftype == NL80211_IFTYPE_AP ||
wdev->iftype == NL80211_IFTYPE_P2P_GO)
wilc_wfi_deinit_mon_interface(wl, true);
vif = netdev_priv(wdev->netdev);
cfg80211_stop_iface(wiphy, wdev, GFP_KERNEL);
unregister_netdevice(vif->ndev);
vif->monitor_flag = 0;
mutex_lock(&wl->vif_mutex);
wilc_set_wfi_drv_handler(vif, 0, 0, 0);
for (i = vif->idx; i < wl->vif_num ; i++) {
if ((i + 1) >= wl->vif_num) {
wl->vif[i] = NULL;
} else {
vif = wl->vif[i + 1];
vif->ifc_id = i;
vif->idx = i;
wl->vif[i] = vif;
wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
vif->iftype, vif->ifc_id);
}
}
wl->vif_num--;
mutex_unlock(&wl->vif_mutex);
return 0; return 0;
} }
static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc)) if (!wow && wilc_wlan_get_num_conn_ifcs(wl))
vif->wilc->suspend_event = true; wl->suspend_event = true;
else else
vif->wilc->suspend_event = false; wl->suspend_event = false;
return 0; return 0;
} }
static int wilc_resume(struct wiphy *wiphy) static int wilc_resume(struct wiphy *wiphy)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
netdev_info(vif->ndev, "cfg resume\n");
return 0; return 0;
} }
static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled) static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
{ {
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc *wl = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_vif *vif;
mutex_lock(&wl->vif_mutex);
vif = wilc_get_wl_to_vif(wl);
if (IS_ERR(vif)) {
mutex_unlock(&wl->vif_mutex);
return;
}
netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled); netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
mutex_unlock(&wl->vif_mutex);
} }
static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
...@@ -1606,8 +1744,7 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -1606,8 +1744,7 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
{ {
int ret; int ret;
s32 tx_power = MBM_TO_DBM(mbm); s32 tx_power = MBM_TO_DBM(mbm);
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_vif *vif = netdev_priv(priv->dev);
if (tx_power < 0) if (tx_power < 0)
tx_power = 0; tx_power = 0;
...@@ -1624,8 +1761,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -1624,8 +1761,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
int *dbm) int *dbm)
{ {
int ret; int ret;
struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc_vif *vif = netdev_priv(priv->dev);
struct wilc *wl = vif->wilc; struct wilc *wl = vif->wilc;
/* If firmware is not started, return. */ /* If firmware is not started, return. */
...@@ -1682,98 +1818,137 @@ static const struct cfg80211_ops wilc_cfg80211_ops = { ...@@ -1682,98 +1818,137 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
}; };
static struct wireless_dev *wilc_wfi_cfg_alloc(void) static void wlan_init_locks(struct wilc *wl)
{ {
struct wireless_dev *wdev; mutex_init(&wl->hif_cs);
mutex_init(&wl->rxq_cs);
mutex_init(&wl->cfg_cmd_lock);
mutex_init(&wl->vif_mutex);
spin_lock_init(&wl->txq_spinlock);
mutex_init(&wl->txq_add_to_head_cs);
init_completion(&wl->txq_event);
init_completion(&wl->cfg_event);
init_completion(&wl->sync_event);
init_completion(&wl->txq_thread_started);
}
wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
if (!wdev) const struct wilc_hif_func *ops)
goto out; {
struct wilc *wl;
struct wilc_vif *vif;
int ret;
wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv)); wl = wilc_create_wiphy(dev);
if (!wdev->wiphy) if (!wl)
goto free_mem; return -EINVAL;
return wdev; ret = wilc_wlan_cfg_init(wl);
if (ret)
goto free_wl;
free_mem: *wilc = wl;
kfree(wdev); wl->io_type = io_type;
out: wl->hif_func = ops;
return NULL; wl->enable_ps = false;
wl->chip_ps_state = WILC_CHIP_WAKEDUP;
INIT_LIST_HEAD(&wl->txq_head.list);
INIT_LIST_HEAD(&wl->rxq_head.list);
wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
if (!wl->hif_workqueue) {
ret = -ENOMEM;
goto free_cfg;
}
vif = wilc_netdev_ifc_init(wl, "wlan%d", WILC_STATION_MODE,
NL80211_IFTYPE_STATION, false);
if (IS_ERR(vif)) {
ret = PTR_ERR(vif);
goto free_hq;
}
wlan_init_locks(wl);
return 0;
free_hq:
destroy_workqueue(wl->hif_workqueue);
free_cfg:
wilc_wlan_cfg_deinit(wl);
free_wl:
wiphy_unregister(wl->wiphy);
wiphy_free(wl->wiphy);
return ret;
} }
EXPORT_SYMBOL_GPL(wilc_cfg80211_init);
struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct wilc *wilc_create_wiphy(struct device *dev)
struct device *dev)
{ {
struct wilc_priv *priv; struct wiphy *wiphy;
struct wireless_dev *wdev; struct wilc *wl;
int ret; int ret;
wdev = wilc_wfi_cfg_alloc(); wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));
if (!wdev) { if (!wiphy)
netdev_err(net, "wiphy new allocate failed\n");
return NULL; return NULL;
}
priv = wdev_priv(wdev); wl = wiphy_priv(wiphy);
priv->wdev = wdev;
memcpy(priv->bitrates, wilc_bitrates, sizeof(wilc_bitrates)); memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
memcpy(priv->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels)); memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
priv->band.bitrates = priv->bitrates; wl->band.bitrates = wl->bitrates;
priv->band.n_bitrates = ARRAY_SIZE(priv->bitrates); wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);
priv->band.channels = priv->channels; wl->band.channels = wl->channels;
priv->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels); wl->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
priv->band.ht_cap.ht_supported = 1; wl->band.ht_cap.ht_supported = 1;
priv->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
priv->band.ht_cap.mcs.rx_mask[0] = 0xff; wl->band.ht_cap.mcs.rx_mask[0] = 0xff;
priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K; wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
priv->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; wl->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
wdev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; wiphy->bands[NL80211_BAND_2GHZ] = &wl->band;
wdev->wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID; wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
#ifdef CONFIG_PM #ifdef CONFIG_PM
wdev->wiphy->wowlan = &wowlan_support; wiphy->wowlan = &wowlan_support;
#endif #endif
wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
wdev->wiphy->max_scan_ie_len = 1000; wiphy->max_scan_ie_len = 1000;
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
memcpy(priv->cipher_suites, wilc_cipher_suites, memcpy(wl->cipher_suites, wilc_cipher_suites,
sizeof(wilc_cipher_suites)); sizeof(wilc_cipher_suites));
wdev->wiphy->cipher_suites = priv->cipher_suites; wiphy->cipher_suites = wl->cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites); wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types; wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
wdev->wiphy->max_remain_on_channel_duration = 500; wiphy->max_remain_on_channel_duration = 500;
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_MONITOR) |
BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT); BIT(NL80211_IFTYPE_P2P_CLIENT);
wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wdev->iftype = NL80211_IFTYPE_STATION;
set_wiphy_dev(wdev->wiphy, dev); set_wiphy_dev(wiphy, dev);
wl->wiphy = wiphy;
ret = wiphy_register(wdev->wiphy); ret = wiphy_register(wiphy);
if (ret) { if (ret) {
netdev_err(net, "Cannot register wiphy device\n"); wiphy_free(wiphy);
wiphy_free(wdev->wiphy);
kfree(wdev);
return NULL; return NULL;
} }
return wl;
priv->dev = net;
return wdev;
} }
int wilc_init_host_int(struct net_device *net) int wilc_init_host_int(struct net_device *net)
{ {
int ret; int ret;
struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); struct wilc_vif *vif = netdev_priv(net);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
timer_setup(&vif->during_ip_timer, clear_during_ip, 0); timer_setup(&vif->during_ip_timer, clear_during_ip, 0);
...@@ -1790,8 +1965,8 @@ int wilc_init_host_int(struct net_device *net) ...@@ -1790,8 +1965,8 @@ int wilc_init_host_int(struct net_device *net)
void wilc_deinit_host_int(struct net_device *net) void wilc_deinit_host_int(struct net_device *net)
{ {
int ret; int ret;
struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); struct wilc_vif *vif = netdev_priv(net);
struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc_priv *priv = &vif->priv;
priv->p2p_listen_state = false; priv->p2p_listen_state = false;
...@@ -1804,19 +1979,3 @@ void wilc_deinit_host_int(struct net_device *net) ...@@ -1804,19 +1979,3 @@ void wilc_deinit_host_int(struct net_device *net)
netdev_err(net, "Error while deinitializing host interface\n"); netdev_err(net, "Error while deinitializing host interface\n");
} }
void wilc_free_wiphy(struct net_device *net)
{
if (!net)
return;
if (!net->ieee80211_ptr)
return;
if (!net->ieee80211_ptr->wiphy)
return;
wiphy_unregister(net->ieee80211_ptr->wiphy);
wiphy_free(net->ieee80211_ptr->wiphy);
kfree(net->ieee80211_ptr);
}
...@@ -8,17 +8,20 @@ ...@@ -8,17 +8,20 @@
#define NM_WFI_CFGOPERATIONS #define NM_WFI_CFGOPERATIONS
#include "wilc_wfi_netdevice.h" #include "wilc_wfi_netdevice.h"
struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct wiphy *wilc_cfg_alloc(void);
struct device *dev); int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
void wilc_free_wiphy(struct net_device *net); const struct wilc_hif_func *ops);
struct wilc *wilc_create_wiphy(struct device *dev);
void wilc_deinit_host_int(struct net_device *net); void wilc_deinit_host_int(struct net_device *net);
int wilc_init_host_int(struct net_device *net); int wilc_init_host_int(struct net_device *net);
void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
void wilc_wfi_deinit_mon_interface(struct wilc *wl); struct wilc_vif *wilc_netdev_interface(struct wilc *wl, const char *name,
enum nl80211_iftype type);
void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked);
struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
const char *name, const char *name,
struct net_device *real_dev); struct net_device *real_dev);
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
u16 frame_type, bool reg); u16 frame_type, bool reg);
struct wilc_vif *wilc_get_interface(struct wilc *wl);
#endif #endif
...@@ -129,7 +129,7 @@ static struct ieee80211_rate wilc_bitrates[] = { ...@@ -129,7 +129,7 @@ static struct ieee80211_rate wilc_bitrates[] = {
}; };
struct wilc_priv { struct wilc_priv {
struct wireless_dev *wdev; struct wireless_dev wdev;
struct cfg80211_scan_request *scan_req; struct cfg80211_scan_request *scan_req;
struct wilc_wfi_p2p_listen_params remain_on_ch_params; struct wilc_wfi_p2p_listen_params remain_on_ch_params;
...@@ -156,10 +156,6 @@ struct wilc_priv { ...@@ -156,10 +156,6 @@ struct wilc_priv {
int scanned_cnt; int scanned_cnt;
struct wilc_p2p_var p2p; struct wilc_p2p_var p2p;
struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
struct ieee80211_supported_band band;
u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
u64 inc_roc_cookie; u64 inc_roc_cookie;
}; };
...@@ -214,9 +210,11 @@ struct wilc_vif { ...@@ -214,9 +210,11 @@ struct wilc_vif {
struct rf_info periodic_stat; struct rf_info periodic_stat;
struct tcp_ack_filter ack_filter; struct tcp_ack_filter ack_filter;
bool connecting; bool connecting;
struct wilc_priv priv;
}; };
struct wilc { struct wilc {
struct wiphy *wiphy;
const struct wilc_hif_func *hif_func; const struct wilc_hif_func *hif_func;
int io_type; int io_type;
s8 mac_status; s8 mac_status;
...@@ -226,6 +224,8 @@ struct wilc { ...@@ -226,6 +224,8 @@ struct wilc {
int close; int close;
u8 vif_num; u8 vif_num;
struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC]; struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC];
/*protect vif list*/
struct mutex vif_mutex;
u8 open_ifcs; u8 open_ifcs;
/*protect head of transmit queue*/ /*protect head of transmit queue*/
struct mutex txq_add_to_head_cs; struct mutex txq_add_to_head_cs;
...@@ -275,6 +275,10 @@ struct wilc { ...@@ -275,6 +275,10 @@ struct wilc {
struct mutex deinit_lock; struct mutex deinit_lock;
u8 sta_ch; u8 sta_ch;
u8 op_ch; u8 op_ch;
struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
struct ieee80211_supported_band band;
u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
}; };
struct wilc_wfi_mon_priv { struct wilc_wfi_mon_priv {
...@@ -284,9 +288,9 @@ struct wilc_wfi_mon_priv { ...@@ -284,9 +288,9 @@ struct wilc_wfi_mon_priv {
void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
void wilc_mac_indicate(struct wilc *wilc); void wilc_mac_indicate(struct wilc *wilc);
void wilc_netdev_cleanup(struct wilc *wilc); void wilc_netdev_cleanup(struct wilc *wilc);
int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
const struct wilc_hif_func *ops);
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode); void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode);
struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
int vif_type, enum nl80211_iftype type,
bool rtnl_locked);
#endif #endif
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/ip.h> #include <linux/ip.h>
#include "wilc_wfi_netdevice.h" #include "wilc_wfi_cfgoperations.h"
#include "wilc_wlan_cfg.h" #include "wilc_wlan_cfg.h"
static inline bool is_wilc1000(u32 id) static inline bool is_wilc1000(u32 id)
...@@ -267,6 +267,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, ...@@ -267,6 +267,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
tqe->tx_complete_func = NULL; tqe->tx_complete_func = NULL;
tqe->priv = NULL; tqe->priv = NULL;
tqe->ack_idx = NOT_TCP_ACK; tqe->ack_idx = NOT_TCP_ACK;
tqe->vif = vif;
wilc_wlan_txq_add_to_head(vif, tqe); wilc_wlan_txq_add_to_head(vif, tqe);
...@@ -295,6 +296,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, ...@@ -295,6 +296,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->buffer_size = buffer_size; tqe->buffer_size = buffer_size;
tqe->tx_complete_func = tx_complete_fn; tqe->tx_complete_func = tx_complete_fn;
tqe->priv = priv; tqe->priv = priv;
tqe->vif = vif;
tqe->ack_idx = NOT_TCP_ACK; tqe->ack_idx = NOT_TCP_ACK;
if (vif->ack_filter.enabled) if (vif->ack_filter.enabled)
...@@ -326,6 +328,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, ...@@ -326,6 +328,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->tx_complete_func = tx_complete_fn; tqe->tx_complete_func = tx_complete_fn;
tqe->priv = priv; tqe->priv = priv;
tqe->ack_idx = NOT_TCP_ACK; tqe->ack_idx = NOT_TCP_ACK;
tqe->vif = vif;
wilc_wlan_txq_add_to_tail(dev, tqe); wilc_wlan_txq_add_to_tail(dev, tqe);
return 1; return 1;
} }
...@@ -482,7 +485,7 @@ void host_sleep_notify(struct wilc *wilc) ...@@ -482,7 +485,7 @@ void host_sleep_notify(struct wilc *wilc)
} }
EXPORT_SYMBOL_GPL(host_sleep_notify); EXPORT_SYMBOL_GPL(host_sleep_notify);
int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
{ {
int i, entries = 0; int i, entries = 0;
u32 sum; u32 sum;
...@@ -494,17 +497,20 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) ...@@ -494,17 +497,20 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
int counter; int counter;
int timeout; int timeout;
u32 vmm_table[WILC_VMM_TBL_SIZE]; u32 vmm_table[WILC_VMM_TBL_SIZE];
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
const struct wilc_hif_func *func; const struct wilc_hif_func *func;
u8 *txb = wilc->tx_buffer; u8 *txb = wilc->tx_buffer;
struct net_device *dev;
struct wilc_vif *vif;
if (wilc->quit) if (wilc->quit)
goto out; goto out;
mutex_lock(&wilc->txq_add_to_head_cs); mutex_lock(&wilc->txq_add_to_head_cs);
wilc_wlan_txq_filter_dup_tcp_ack(dev);
tqe = wilc_wlan_txq_get_first(wilc); tqe = wilc_wlan_txq_get_first(wilc);
if (!tqe)
goto out;
dev = tqe->vif->ndev;
wilc_wlan_txq_filter_dup_tcp_ack(dev);
i = 0; i = 0;
sum = 0; sum = 0;
do { do {
...@@ -629,6 +635,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) ...@@ -629,6 +635,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
if (!tqe) if (!tqe)
break; break;
vif = tqe->vif;
if (vmm_table[i] == 0) if (vmm_table[i] == 0)
break; break;
...@@ -648,8 +655,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) ...@@ -648,8 +655,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
if (tqe->type == WILC_CFG_PKT) { if (tqe->type == WILC_CFG_PKT) {
buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
} else if (tqe->type == WILC_NET_PKT) { } else if (tqe->type == WILC_NET_PKT) {
bssid = ((struct tx_complete_data *)(tqe->priv))->bssid; bssid = tqe->vif->bssid;
buffer_offset = ETH_ETHERNET_HDR_OFFSET; buffer_offset = ETH_ETHERNET_HDR_OFFSET;
memcpy(&txb[offset + 8], bssid, 6); memcpy(&txb[offset + 8], bssid, 6);
} else { } else {
......
...@@ -216,6 +216,7 @@ struct txq_entry_t { ...@@ -216,6 +216,7 @@ struct txq_entry_t {
int buffer_size; int buffer_size;
void *priv; void *priv;
int status; int status;
struct wilc_vif *vif;
void (*tx_complete_func)(void *priv, int status); void (*tx_complete_func)(void *priv, int status);
}; };
...@@ -253,7 +254,6 @@ struct wilc_hif_func { ...@@ -253,7 +254,6 @@ struct wilc_hif_func {
struct tx_complete_data { struct tx_complete_data {
int size; int size;
void *buff; void *buff;
u8 *bssid;
struct sk_buff *skb; struct sk_buff *skb;
}; };
...@@ -284,7 +284,7 @@ int wilc_wlan_stop(struct wilc *wilc); ...@@ -284,7 +284,7 @@ int wilc_wlan_stop(struct wilc *wilc);
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, u32 buffer_size,
void (*tx_complete_fn)(void *, int)); void (*tx_complete_fn)(void *, int));
int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count); int wilc_wlan_handle_txq(struct wilc *wl, u32 *txq_count);
void wilc_handle_isr(struct wilc *wilc); void wilc_handle_isr(struct wilc *wilc);
void wilc_wlan_cleanup(struct net_device *dev); void wilc_wlan_cleanup(struct net_device *dev);
int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
...@@ -301,7 +301,7 @@ void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); ...@@ -301,7 +301,7 @@ void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value);
int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc); int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc);
netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
void host_wakeup_notify(struct wilc *wilc); void host_wakeup_notify(struct wilc *wilc);
void host_sleep_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc);
void chip_allow_sleep(struct wilc *wilc); void chip_allow_sleep(struct wilc *wilc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment