summaryrefslogtreecommitdiffstats
path: root/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
diff options
context:
space:
mode:
authorAjay Singh2019-06-26 14:40:52 +0200
committerGreg Kroah-Hartman2019-07-01 09:01:41 +0200
commit9bc061e880548710b5a09d7ae4e0195b2ed496d4 (patch)
tree68407c91ea36ca7ff6e65c58cbb2cfabf5e62294 /drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
parentstaging: wilc1000: fix error path cleanup in wilc_wlan_initialize() (diff)
downloadkernel-qcow2-linux-9bc061e880548710b5a09d7ae4e0195b2ed496d4.tar.gz
kernel-qcow2-linux-9bc061e880548710b5a09d7ae4e0195b2ed496d4.tar.xz
kernel-qcow2-linux-9bc061e880548710b5a09d7ae4e0195b2ed496d4.zip
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: Ajay Singh <ajay.kathat@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/wilc1000/wilc_wfi_cfgoperations.c')
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c535
1 files changed, 347 insertions, 188 deletions
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index b0daa1136663..012e3252cacc 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -183,48 +183,67 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
eth_zero_addr(priv->associated_bss);
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;
-
- if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
- reason = 3;
- else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
- reason = 1;
+ } else {
+ if (wfi_drv->ifc_up)
+ reason = 3;
+ else
+ reason = 1;
+ }
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,
struct cfg80211_chan_def *chandef)
{
- u32 channelnum = 0;
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
- int result = 0;
+ struct wilc *wl = wiphy_priv(wiphy);
+ struct wilc_vif *vif;
+ u32 channelnum;
+ 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);
- vif->wilc->op_ch = channelnum;
+ wl->op_ch = channelnum;
result = wilc_set_mac_chnl_num(vif, channelnum);
+ if (result)
+ netdev_err(vif->ndev, "Error in setting channel\n");
- if (result != 0)
- netdev_err(priv->dev, "Error in setting channel\n");
-
+ mutex_unlock(&wl->vif_mutex);
return result;
}
static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(request->wdev->netdev);
+ struct wilc_priv *priv = &vif->priv;
u32 i;
int ret = 0;
u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];
u8 scan_type;
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;
}
@@ -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,
struct cfg80211_connect_params *sme)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
struct host_if_drv *wfi_drv = priv->hif_drv;
int ret;
u32 i;
@@ -410,8 +429,8 @@ out_error:
static int disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
struct wilc *wilc = vif->wilc;
int ret;
@@ -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;
- struct wilc_priv *priv = wiphy_priv(wiphy);
const u8 *rx_mic = NULL;
const u8 *tx_mic = NULL;
u8 mode = WILC_FW_SEC_NO;
u8 op_mode;
struct wilc_vif *vif = netdev_priv(netdev);
+ struct wilc_priv *priv = &vif->priv;
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
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);
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,
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
- if (priv->wdev->iftype == NL80211_IFTYPE_AP ||
- priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
+ if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
+ priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
struct wilc_wfi_key *key;
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,
bool pairwise,
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 *wl = vif->wilc;
+ struct wilc_priv *priv = &vif->priv;
if (netdev == wl->vif[0]->ndev) {
if (priv->wilc_gtk[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,
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;
if (!pairwise) {
@@ -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,
u8 key_index, bool unicast, bool multicast)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(netdev);
wilc_set_wep_default_keyid(vif, key_index);
@@ -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,
const u8 *mac, struct station_info *sinfo)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
u32 i = 0;
u32 associatedsta = ~0;
u32 inactive_time = 0;
@@ -743,13 +762,35 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev,
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)
{
int ret;
struct cfg_param_attr cfg_param_val;
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc *wl = wiphy_priv(wiphy);
+ 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;
if (changed & WIPHY_PARAM_RETRY_SHORT) {
@@ -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,
struct cfg80211_pmksa *pmksa)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(netdev);
+ struct wilc_priv *priv = &vif->priv;
u32 i;
int ret = 0;
u8 flag = 0;
@@ -840,7 +881,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
{
u32 i;
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++) {
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,
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;
}
@@ -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_priv *priv = &vif->priv;
+ struct host_if_drv *wfi_drv = priv->hif_drv;
u32 header, pkt_offset;
s32 freq;
__le16 fc;
@@ -1008,8 +1049,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
pkt_offset & IS_MGMT_STATUS_SUCCES)
ack = true;
- cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size,
- ack, GFP_KERNEL);
+ cfg80211_mgmt_tx_status(&priv->wdev, priv->tx_cookie, buff,
+ size, ack, GFP_KERNEL);
return;
}
@@ -1017,13 +1058,13 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
fc = ((struct ieee80211_hdr *)buff)->frame_control;
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;
}
if (priv->cfg_scanning &&
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;
}
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)
break;
default:
- netdev_dbg(dev,
+ netdev_dbg(vif->ndev,
"%s: Not handled action frame type:%x\n",
__func__, buff[ACTION_SUBTYPE_ID]);
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)
@@ -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)
{
- 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;
if (cookie != params->listen_cookie)
@@ -1074,7 +1116,7 @@ static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
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);
}
@@ -1084,8 +1126,8 @@ static int remain_on_channel(struct wiphy *wiphy,
unsigned int duration, u64 *cookie)
{
int ret = 0;
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(wdev->netdev);
+ struct wilc_priv *priv = &vif->priv;
u64 id;
if (wdev->iftype == NL80211_IFTYPE_AP) {
@@ -1099,7 +1141,7 @@ static int remain_on_channel(struct wiphy *wiphy,
ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
wilc_wfi_remain_on_channel_expired,
- (void *)priv);
+ (void *)vif);
if (ret)
return ret;
@@ -1122,8 +1164,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
u64 cookie)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(wdev->netdev);
+ struct wilc_priv *priv = &vif->priv;
if (cookie != priv->remain_on_ch_params.listen_cookie)
return -ENOENT;
@@ -1193,9 +1235,9 @@ static int mgmt_tx(struct wiphy *wiphy,
size_t len = params->len;
const struct ieee80211_mgmt *mgmt;
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_priv *priv = &vif->priv;
+ struct host_if_drv *wfi_drv = priv->hif_drv;
u32 buf_len = len + sizeof(p2p_vendor_spec) +
sizeof(priv->p2p.local_random);
int ret = 0;
@@ -1279,7 +1321,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
struct wireless_dev *wdev,
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;
wfi_drv->p2p_timeout = jiffies;
@@ -1289,7 +1332,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
params = &priv->remain_on_ch_params;
- cfg80211_remain_on_channel_expired(priv->wdev,
+ cfg80211_remain_on_channel_expired(wdev,
params->listen_cookie,
params->listen_ch,
GFP_KERNEL);
@@ -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,
u16 frame_type, bool reg)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
- struct wilc *wl = vif->wilc;
+ struct wilc *wl = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(wdev->netdev);
if (!frame_type)
return;
@@ -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,
int idx, u8 *mac, struct station_info *sinfo)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
int ret;
if (idx != 0)
@@ -1350,15 +1391,15 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev,
if (ret)
return ret;
- memcpy(mac, priv->associated_bss, ETH_ALEN);
+ memcpy(mac, vif->priv.associated_bss, ETH_ALEN);
return 0;
}
static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
bool enabled, int timeout)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
if (!priv->hif_drv)
return -EIO;
@@ -1373,9 +1414,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
enum nl80211_iftype type,
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 *wl = vif->wilc;
+ struct wilc_priv *priv = &vif->priv;
priv->p2p.local_random = 0x01;
priv->p2p.recv_random = 0x00;
@@ -1387,8 +1428,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_STATION:
vif->connecting = false;
dev->ieee80211_ptr->iftype = type;
- priv->wdev->iftype = type;
+ priv->wdev.iftype = type;
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;
wilc_set_operation_mode(vif, WILC_STATION_MODE);
@@ -1402,7 +1445,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_P2P_CLIENT:
vif->connecting = false;
dev->ieee80211_ptr->iftype = type;
- priv->wdev->iftype = type;
+ priv->wdev.iftype = type;
vif->monitor_flag = 0;
vif->iftype = WILC_CLIENT_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,
case NL80211_IFTYPE_AP:
wl->enable_ps = false;
dev->ieee80211_ptr->iftype = type;
- priv->wdev->iftype = type;
+ priv->wdev.iftype = type;
vif->iftype = WILC_AP_MODE;
if (wl->initialized) {
@@ -1431,7 +1474,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS));
wilc_set_operation_mode(vif, WILC_AP_MODE);
dev->ieee80211_ptr->iftype = type;
- priv->wdev->iftype = type;
+ priv->wdev.iftype = type;
vif->iftype = WILC_GO_MODE;
wl->enable_ps = false;
@@ -1450,14 +1493,13 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ap_settings *settings)
{
struct wilc_vif *vif = netdev_priv(dev);
- struct wilc *wl = vif->wilc;
int ret;
ret = set_channel(wiphy, &settings->chandef);
if (ret != 0)
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);
return wilc_add_beacon(vif, settings->beacon_interval,
@@ -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,
struct cfg80211_beacon_data *beacon)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
return wilc_add_beacon(vif, 0, 0, beacon);
}
@@ -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)
{
int ret;
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(dev);
wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);
@@ -1493,8 +1533,8 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac, struct station_parameters *params)
{
int ret = 0;
- struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {
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,
{
const u8 *mac = params->mac;
int ret = 0;
- struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc_priv *priv = &vif->priv;
struct sta_info *info;
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,
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,
const char *name,
unsigned char name_assign_type,
enum nl80211_iftype type,
struct vif_params *params)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
- struct net_device *new_ifc;
+ struct wilc *wl = wiphy_priv(wiphy);
+ struct wilc_vif *vif;
+ struct wireless_dev *wdev;
+ int iftype;
+ int ret;
if (type == NL80211_IFTYPE_MONITOR) {
- new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name,
- vif->ndev);
- if (new_ifc) {
- vif = netdev_priv(priv->wdev->netdev);
- vif->monitor_flag = 1;
+ struct net_device *ndev;
+ int ap_index = wilc_get_vif_from_type(wl, WILC_AP_MODE);
+
+ 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;
+ 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)
{
+ 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;
}
static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc *wl = wiphy_priv(wiphy);
- if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
- vif->wilc->suspend_event = true;
+ if (!wow && wilc_wlan_get_num_conn_ifcs(wl))
+ wl->suspend_event = true;
else
- vif->wilc->suspend_event = false;
+ wl->suspend_event = false;
return 0;
}
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;
}
static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
{
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc *wl = wiphy_priv(wiphy);
+ 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);
+ mutex_unlock(&wl->vif_mutex);
}
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;
s32 tx_power = MBM_TO_DBM(mbm);
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(wdev->netdev);
if (tx_power < 0)
tx_power = 0;
@@ -1624,8 +1761,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
int *dbm)
{
int ret;
- struct wilc_priv *priv = wiphy_priv(wiphy);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(wdev->netdev);
struct wilc *wl = vif->wilc;
/* If firmware is not started, return. */
@@ -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);
- if (!wdev)
- goto out;
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+ const struct wilc_hif_func *ops)
+{
+ struct wilc *wl;
+ struct wilc_vif *vif;
+ int ret;
- wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
- if (!wdev->wiphy)
- goto free_mem;
+ wl = wilc_create_wiphy(dev);
+ if (!wl)
+ return -EINVAL;
- return wdev;
+ 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 = 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;
+ }
-free_mem:
- kfree(wdev);
-out:
- return NULL;
+ 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 device *dev)
+struct wilc *wilc_create_wiphy(struct device *dev)
{
- struct wilc_priv *priv;
- struct wireless_dev *wdev;
+ struct wiphy *wiphy;
+ struct wilc *wl;
int ret;
- wdev = wilc_wfi_cfg_alloc();
- if (!wdev) {
- netdev_err(net, "wiphy new allocate failed\n");
+ wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));
+ if (!wiphy)
return NULL;
- }
- priv = wdev_priv(wdev);
- priv->wdev = wdev;
+ wl = wiphy_priv(wiphy);
- memcpy(priv->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
- memcpy(priv->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
- priv->band.bitrates = priv->bitrates;
- priv->band.n_bitrates = ARRAY_SIZE(priv->bitrates);
- priv->band.channels = priv->channels;
- priv->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
+ memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
+ memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
+ wl->band.bitrates = wl->bitrates;
+ wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);
+ wl->band.channels = wl->channels;
+ wl->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
- priv->band.ht_cap.ht_supported = 1;
- priv->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
- priv->band.ht_cap.mcs.rx_mask[0] = 0xff;
- priv->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.ht_supported = 1;
+ wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+ wl->band.ht_cap.mcs.rx_mask[0] = 0xff;
+ wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+ 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
- wdev->wiphy->wowlan = &wowlan_support;
+ wiphy->wowlan = &wowlan_support;
#endif
- wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
- wdev->wiphy->max_scan_ie_len = 1000;
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
- memcpy(priv->cipher_suites, wilc_cipher_suites,
+ wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
+ wiphy->max_scan_ie_len = 1000;
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ memcpy(wl->cipher_suites, wilc_cipher_suites,
sizeof(wilc_cipher_suites));
- wdev->wiphy->cipher_suites = priv->cipher_suites;
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
- wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
-
- wdev->wiphy->max_remain_on_channel_duration = 500;
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MONITOR) |
- BIT(NL80211_IFTYPE_P2P_GO) |
- BIT(NL80211_IFTYPE_P2P_CLIENT);
- wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- wdev->iftype = NL80211_IFTYPE_STATION;
-
- set_wiphy_dev(wdev->wiphy, dev);
-
- ret = wiphy_register(wdev->wiphy);
+ wiphy->cipher_suites = wl->cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
+ wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
+
+ wiphy->max_remain_on_channel_duration = 500;
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MONITOR) |
+ BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT);
+ wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+
+ set_wiphy_dev(wiphy, dev);
+ wl->wiphy = wiphy;
+ ret = wiphy_register(wiphy);
if (ret) {
- netdev_err(net, "Cannot register wiphy device\n");
- wiphy_free(wdev->wiphy);
- kfree(wdev);
+ wiphy_free(wiphy);
return NULL;
}
-
- priv->dev = net;
- return wdev;
+ return wl;
}
int wilc_init_host_int(struct net_device *net)
{
int ret;
- struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(net);
+ struct wilc_priv *priv = &vif->priv;
timer_setup(&vif->during_ip_timer, clear_during_ip, 0);
@@ -1790,8 +1965,8 @@ int wilc_init_host_int(struct net_device *net)
void wilc_deinit_host_int(struct net_device *net)
{
int ret;
- struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
- struct wilc_vif *vif = netdev_priv(priv->dev);
+ struct wilc_vif *vif = netdev_priv(net);
+ struct wilc_priv *priv = &vif->priv;
priv->p2p_listen_state = false;
@@ -1804,19 +1979,3 @@ void wilc_deinit_host_int(struct net_device *net)
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);
-}