提交 55055976 编写于 作者: V Vasanthakumar Thiagarajan 提交者: Kalle Valo

ath6kl: Implement add_virtual_intf() and del_virtual_intf()

Signed-off-by: NVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 7b85832d
...@@ -293,6 +293,57 @@ static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies, ...@@ -293,6 +293,57 @@ static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies,
return ret; return ret;
} }
static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
{
switch (type) {
case NL80211_IFTYPE_STATION:
*nw_type = INFRA_NETWORK;
break;
case NL80211_IFTYPE_ADHOC:
*nw_type = ADHOC_NETWORK;
break;
case NL80211_IFTYPE_AP:
*nw_type = AP_NETWORK;
break;
case NL80211_IFTYPE_P2P_CLIENT:
*nw_type = INFRA_NETWORK;
break;
case NL80211_IFTYPE_P2P_GO:
*nw_type = AP_NETWORK;
break;
default:
ath6kl_err("invalid interface type %u\n", type);
return -ENOTSUPP;
}
return 0;
}
static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
u8 *if_idx, u8 *nw_type)
{
int i;
if (ath6kl_nliftype_to_drv_iftype(type, nw_type))
return false;
if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
ar->num_vif))
return false;
if (type == NL80211_IFTYPE_STATION ||
type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
for (i = 0; i < MAX_NUM_VIF; i++) {
if ((ar->avail_idx_map >> i) & BIT(0)) {
*if_idx = i;
return true;
}
}
}
return false;
}
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme) struct cfg80211_connect_params *sme)
{ {
...@@ -1206,6 +1257,52 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy, ...@@ -1206,6 +1257,52 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
return 0; return 0;
} }
static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params)
{
struct ath6kl *ar = wiphy_priv(wiphy);
struct net_device *ndev;
u8 if_idx, nw_type;
if (ar->num_vif == MAX_NUM_VIF) {
ath6kl_err("Reached maximum number of supported vif\n");
return ERR_PTR(-EINVAL);
}
if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
ath6kl_err("Not a supported interface type\n");
return ERR_PTR(-EINVAL);
}
ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
if (!ndev)
return ERR_PTR(-ENOMEM);
ar->num_vif++;
return ndev;
}
static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
struct net_device *ndev)
{
struct ath6kl *ar = wiphy_priv(wiphy);
struct ath6kl_vif *vif = netdev_priv(ndev);
spin_lock(&ar->list_lock);
list_del(&vif->list);
spin_unlock(&ar->list_lock);
ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
ath6kl_deinit_if_data(vif);
return 0;
}
static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
struct net_device *ndev, struct net_device *ndev,
enum nl80211_iftype type, u32 *flags, enum nl80211_iftype type, u32 *flags,
...@@ -1947,6 +2044,8 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { ...@@ -1947,6 +2044,8 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
}; };
static struct cfg80211_ops ath6kl_cfg80211_ops = { static struct cfg80211_ops ath6kl_cfg80211_ops = {
.add_virtual_intf = ath6kl_cfg80211_add_iface,
.del_virtual_intf = ath6kl_cfg80211_del_iface,
.change_virtual_intf = ath6kl_cfg80211_change_iface, .change_virtual_intf = ath6kl_cfg80211_change_iface,
.scan = ath6kl_cfg80211_scan, .scan = ath6kl_cfg80211_scan,
.connect = ath6kl_cfg80211_connect, .connect = ath6kl_cfg80211_connect,
...@@ -2097,18 +2196,28 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) ...@@ -2097,18 +2196,28 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif)
void ath6kl_deinit_if_data(struct ath6kl_vif *vif) void ath6kl_deinit_if_data(struct ath6kl_vif *vif)
{ {
struct ath6kl *ar = vif->ar;
aggr_module_destroy(vif->aggr_cntxt); aggr_module_destroy(vif->aggr_cntxt);
ar->avail_idx_map |= BIT(vif->fw_vif_idx);
if (vif->nw_type == ADHOC_NETWORK)
ar->ibss_if_active = false;
unregister_netdevice(vif->ndev); unregister_netdevice(vif->ndev);
ar->num_vif--;
} }
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type, u8 fw_vif_idx) enum nl80211_iftype type, u8 fw_vif_idx,
u8 nw_type)
{ {
struct net_device *ndev; struct net_device *ndev;
struct ath6kl_vif *vif; struct ath6kl_vif *vif;
ndev = alloc_netdev(sizeof(*vif), "wlan%d", ether_setup); ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
if (!ndev) if (!ndev)
return NULL; return NULL;
...@@ -2121,8 +2230,14 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ...@@ -2121,8 +2230,14 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->wdev.netdev = ndev; vif->wdev.netdev = ndev;
vif->wdev.iftype = type; vif->wdev.iftype = type;
vif->fw_vif_idx = fw_vif_idx; vif->fw_vif_idx = fw_vif_idx;
vif->nw_type = vif->next_mode = nw_type;
ar->wdev = &vif->wdev; ar->wdev = &vif->wdev;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
0x2;
init_netdev(ndev); init_netdev(ndev);
ath6kl_init_control_info(vif); ath6kl_init_control_info(vif);
...@@ -2134,11 +2249,15 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ...@@ -2134,11 +2249,15 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
if (register_netdevice(ndev)) if (register_netdevice(ndev))
goto err; goto err;
ar->avail_idx_map &= ~BIT(fw_vif_idx);
vif->sme_state = SME_DISCONNECTED; vif->sme_state = SME_DISCONNECTED;
set_bit(WLAN_ENABLED, &vif->flags); set_bit(WLAN_ENABLED, &vif->flags);
ar->wlan_pwr_state = WLAN_POWER_STATE_ON; ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
set_bit(NETDEV_REGISTERED, &vif->flags); set_bit(NETDEV_REGISTERED, &vif->flags);
if (type == NL80211_IFTYPE_ADHOC)
ar->ibss_if_active = true;
spin_lock(&ar->list_lock); spin_lock(&ar->list_lock);
list_add_tail(&vif->list, &ar->vif_list); list_add_tail(&vif->list, &ar->vif_list);
spin_unlock(&ar->list_lock); spin_unlock(&ar->list_lock);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type, enum nl80211_iftype type,
u8 fw_vif_idx); u8 fw_vif_idx, u8 nw_type);
int ath6kl_register_ieee80211_hw(struct ath6kl *ar); int ath6kl_register_ieee80211_hw(struct ath6kl *ar);
struct ath6kl *ath6kl_core_alloc(struct device *dev); struct ath6kl *ath6kl_core_alloc(struct device *dev);
void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar); void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar);
......
...@@ -460,6 +460,8 @@ struct ath6kl { ...@@ -460,6 +460,8 @@ struct ath6kl {
struct list_head vif_list; struct list_head vif_list;
/* Lock to avoid race in vif_list entries among add/del/traverse */ /* Lock to avoid race in vif_list entries among add/del/traverse */
spinlock_t list_lock; spinlock_t list_lock;
u8 num_vif;
u8 avail_idx_map;
spinlock_t lock; spinlock_t lock;
struct semaphore sem; struct semaphore sem;
u16 listen_intvl_b; u16 listen_intvl_b;
...@@ -470,6 +472,7 @@ struct ath6kl { ...@@ -470,6 +472,7 @@ struct ath6kl {
u8 tx_pwr; u8 tx_pwr;
struct ath6kl_node_mapping node_map[MAX_NODE_NUM]; struct ath6kl_node_mapping node_map[MAX_NODE_NUM];
u8 ibss_ps_enable; u8 ibss_ps_enable;
bool ibss_if_active;
u8 node_num; u8 node_num;
u8 next_ep_id; u8 next_ep_id;
struct ath6kl_cookie *cookie_list; struct ath6kl_cookie *cookie_list;
...@@ -666,4 +669,5 @@ void ath6kl_init_control_info(struct ath6kl_vif *vif); ...@@ -666,4 +669,5 @@ void ath6kl_init_control_info(struct ath6kl_vif *vif);
void ath6kl_deinit_if_data(struct ath6kl_vif *vif); void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
void ath6kl_core_free(struct ath6kl *ar); void ath6kl_core_free(struct ath6kl *ar);
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
#endif /* CORE_H */ #endif /* CORE_H */
...@@ -88,7 +88,6 @@ void ath6kl_init_profile_info(struct ath6kl_vif *vif) ...@@ -88,7 +88,6 @@ void ath6kl_init_profile_info(struct ath6kl_vif *vif)
memset(vif->req_bssid, 0, sizeof(vif->req_bssid)); memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
memset(vif->bssid, 0, sizeof(vif->bssid)); memset(vif->bssid, 0, sizeof(vif->bssid));
vif->bss_ch = 0; vif->bss_ch = 0;
vif->nw_type = vif->next_mode = INFRA_NETWORK;
} }
static int ath6kl_set_host_app_area(struct ath6kl *ar) static int ath6kl_set_host_app_area(struct ath6kl *ar)
...@@ -1414,6 +1413,7 @@ static int ath6kl_init(struct ath6kl *ar) ...@@ -1414,6 +1413,7 @@ static int ath6kl_init(struct ath6kl *ar)
int status = 0; int status = 0;
s32 timeleft; s32 timeleft;
struct net_device *ndev; struct net_device *ndev;
int i;
if (!ar) if (!ar)
return -EIO; return -EIO;
...@@ -1445,10 +1445,14 @@ static int ath6kl_init(struct ath6kl *ar) ...@@ -1445,10 +1445,14 @@ static int ath6kl_init(struct ath6kl *ar)
goto err_node_cleanup; goto err_node_cleanup;
} }
for (i = 0; i < MAX_NUM_VIF; i++)
ar->avail_idx_map |= BIT(i);
rtnl_lock(); rtnl_lock();
/* Add an initial station interface */ /* Add an initial station interface */
ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0); ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
INFRA_NETWORK);
rtnl_unlock(); rtnl_unlock();
...@@ -1632,7 +1636,7 @@ int ath6kl_core_init(struct ath6kl *ar) ...@@ -1632,7 +1636,7 @@ int ath6kl_core_init(struct ath6kl *ar)
return ret; return ret;
} }
static void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
{ {
static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
bool discon_issued; bool discon_issued;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册