diff options
Diffstat (limited to 'drivers/staging/wilc1000/wilc_wfi_cfgoperations.c')
-rw-r--r-- | drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 548 |
1 files changed, 356 insertions, 192 deletions
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index f6825727bf77..d72fdd333050 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -183,47 +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; } @@ -235,9 +255,14 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) scan_ch_list[i] = ieee80211_frequency_to_channel(freq); } - ret = wilc_scan(vif, WILC_FW_USER_SCAN, WILC_FW_ACTIVE_SCAN, - scan_ch_list, request->n_channels, cfg_scan_result, - (void *)priv, request); + if (request->n_ssids) + scan_type = WILC_FW_ACTIVE_SCAN; + else + scan_type = WILC_FW_PASSIVE_SCAN; + + ret = wilc_scan(vif, WILC_FW_USER_SCAN, scan_type, scan_ch_list, + request->n_channels, cfg_scan_result, (void *)priv, + request); if (ret) { priv->scan_req = NULL; @@ -250,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; @@ -404,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; @@ -495,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) @@ -532,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); @@ -605,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]) { @@ -644,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) { @@ -669,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); @@ -680,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; @@ -737,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) { @@ -798,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; @@ -834,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, @@ -864,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; } @@ -981,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; @@ -1002,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; } @@ -1011,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) { @@ -1040,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) @@ -1060,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) @@ -1068,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); } @@ -1078,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) { @@ -1093,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; @@ -1116,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; @@ -1187,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; @@ -1273,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; @@ -1283,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); @@ -1295,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; @@ -1331,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) @@ -1344,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; @@ -1367,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; @@ -1381,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); @@ -1396,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); @@ -1408,12 +1457,12 @@ 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) { wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - 0, vif->ifc_id); + 0, vif->idx); wilc_set_operation_mode(vif, WILC_AP_MODE); wilc_set_power_mgmt(vif, 0, 0); } @@ -1425,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; @@ -1444,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, dev->dev_addr, WILC_AP_MODE); wilc_set_power_mgmt(vif, 0, 0); return wilc_add_beacon(vif, settings->beacon_interval, @@ -1461,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); } @@ -1470,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); @@ -1487,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, @@ -1507,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)) @@ -1539,60 +1585,157 @@ 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; } - return priv->wdev; + + 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; + } + + 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->idx = i; + wl->vif[i] = vif; + wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), + vif->iftype, vif->idx); + } + } + 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, @@ -1600,8 +1743,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; @@ -1618,8 +1760,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. */ @@ -1676,98 +1817,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); @@ -1784,8 +1964,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; @@ -1798,19 +1978,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); -} |