Commit 990bd915 authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by Kalle Valo

ath6kl: Maintain virtual interface in a list

This patch removes all references to ar->vif and takes
vif from a list.
Signed-off-by: default avatarVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 478ac027
...@@ -228,9 +228,9 @@ static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt) ...@@ -228,9 +228,9 @@ static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt)
} }
} }
static bool ath6kl_cfg80211_ready(struct ath6kl *ar) static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
{ {
struct ath6kl_vif *vif = ar->vif; struct ath6kl *ar = vif->ar;
if (!test_bit(WMI_READY, &ar->flag)) { if (!test_bit(WMI_READY, &ar->flag)) {
ath6kl_err("wmi is not ready\n"); ath6kl_err("wmi is not ready\n");
...@@ -302,7 +302,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ...@@ -302,7 +302,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->sme_state = SME_CONNECTING; vif->sme_state = SME_CONNECTING;
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
...@@ -614,7 +614,7 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, ...@@ -614,7 +614,7 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
reason_code); reason_code);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
...@@ -713,7 +713,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ...@@ -713,7 +713,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
int ret = 0; int ret = 0;
u32 force_fg_scan = 0; u32 force_fg_scan = 0;
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (!ar->usr_bss_filter) { if (!ar->usr_bss_filter) {
...@@ -831,7 +831,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, ...@@ -831,7 +831,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_type; u8 key_type;
int status = 0; int status = 0;
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (params->cipher == CCKM_KRK_CIPHER_SUITE) { if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
...@@ -953,7 +953,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, ...@@ -953,7 +953,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
...@@ -980,14 +980,13 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, ...@@ -980,14 +980,13 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
void (*callback) (void *cookie, void (*callback) (void *cookie,
struct key_params *)) struct key_params *))
{ {
struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
struct ath6kl_vif *vif = netdev_priv(ndev); struct ath6kl_vif *vif = netdev_priv(ndev);
struct ath6kl_key *key = NULL; struct ath6kl_key *key = NULL;
struct key_params params; struct key_params params;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
...@@ -1024,7 +1023,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, ...@@ -1024,7 +1023,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
...@@ -1080,12 +1079,17 @@ void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid, ...@@ -1080,12 +1079,17 @@ void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{ {
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif;
int ret; int ret;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
changed); changed);
if (!ath6kl_cfg80211_ready(ar)) vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (changed & WIPHY_PARAM_RTS_THRESHOLD) { if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
...@@ -1108,12 +1112,17 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, ...@@ -1108,12 +1112,17 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
int dbm) int dbm)
{ {
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif;
u8 ath6kl_dbm; u8 ath6kl_dbm;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
type, dbm); type, dbm);
if (!ath6kl_cfg80211_ready(ar)) vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
switch (type) { switch (type) {
...@@ -1128,7 +1137,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, ...@@ -1128,7 +1137,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm); ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
return 0; return 0;
} }
...@@ -1136,15 +1145,19 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, ...@@ -1136,15 +1145,19 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
{ {
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif = ar->vif; struct ath6kl_vif *vif;
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (test_bit(CONNECTED, &vif->flags)) { if (test_bit(CONNECTED, &vif->flags)) {
ar->tx_pwr = 0; ar->tx_pwr = 0;
if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) { if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n"); ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
return -EIO; return -EIO;
} }
...@@ -1173,7 +1186,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy, ...@@ -1173,7 +1186,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n", ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
__func__, pmgmt, timeout); __func__, pmgmt, timeout);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (pmgmt) { if (pmgmt) {
...@@ -1204,7 +1217,7 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, ...@@ -1204,7 +1217,7 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
switch (type) { switch (type) {
...@@ -1241,7 +1254,7 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, ...@@ -1241,7 +1254,7 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev);
int status; int status;
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
vif->ssid_len = ibss_param->ssid_len; vif->ssid_len = ibss_param->ssid_len;
...@@ -1306,10 +1319,9 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, ...@@ -1306,10 +1319,9 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy, static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
struct net_device *dev) struct net_device *dev)
{ {
struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
ath6kl_disconnect(vif); ath6kl_disconnect(vif);
...@@ -1539,10 +1551,9 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, ...@@ -1539,10 +1551,9 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type) enum nl80211_channel_type channel_type)
{ {
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
...@@ -1609,7 +1620,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, ...@@ -1609,7 +1620,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
if (!ath6kl_cfg80211_ready(ar)) if (!ath6kl_cfg80211_ready(vif))
return -EIO; return -EIO;
if (vif->next_mode != AP_NETWORK) if (vif->next_mode != AP_NETWORK)
...@@ -1991,11 +2002,13 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) ...@@ -1991,11 +2002,13 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
spin_lock_init(&ar->lock); spin_lock_init(&ar->lock);
spin_lock_init(&ar->mcastpsq_lock); spin_lock_init(&ar->mcastpsq_lock);
spin_lock_init(&ar->list_lock);
init_waitqueue_head(&ar->event_wq); init_waitqueue_head(&ar->event_wq);
sema_init(&ar->sem, 1); sema_init(&ar->sem, 1);
INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
INIT_LIST_HEAD(&ar->vif_list);
clear_bit(WMI_ENABLED, &ar->flag); clear_bit(WMI_ENABLED, &ar->flag);
clear_bit(SKIP_SCAN, &ar->flag); clear_bit(SKIP_SCAN, &ar->flag);
...@@ -2110,7 +2123,6 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ...@@ -2110,7 +2123,6 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
ndev->ieee80211_ptr = &vif->wdev; ndev->ieee80211_ptr = &vif->wdev;
vif->wdev.wiphy = ar->wiphy; vif->wdev.wiphy = ar->wiphy;
vif->ar = ar; vif->ar = ar;
ar->vif = vif;
vif->ndev = ndev; vif->ndev = ndev;
SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy)); SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
vif->wdev.netdev = ndev; vif->wdev.netdev = ndev;
...@@ -2134,6 +2146,10 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ...@@ -2134,6 +2146,10 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
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);
spin_lock(&ar->list_lock);
list_add_tail(&vif->list, &ar->vif_list);
spin_unlock(&ar->list_lock);
return ndev; return ndev;
err: err:
......
...@@ -397,6 +397,7 @@ enum ath6kl_vif_state { ...@@ -397,6 +397,7 @@ enum ath6kl_vif_state {
}; };
struct ath6kl_vif { struct ath6kl_vif {
struct list_head list;
struct wireless_dev wdev; struct wireless_dev wdev;
struct net_device *ndev; struct net_device *ndev;
struct ath6kl *ar; struct ath6kl *ar;
...@@ -456,7 +457,9 @@ struct ath6kl { ...@@ -456,7 +457,9 @@ struct ath6kl {
int total_tx_data_pend; int total_tx_data_pend;
struct htc_target *htc_target; struct htc_target *htc_target;
void *hif_priv; void *hif_priv;
struct ath6kl_vif *vif; struct list_head vif_list;
/* Lock to avoid race in vif_list entries among add/del/traverse */
spinlock_t list_lock;
spinlock_t lock; spinlock_t lock;
struct semaphore sem; struct semaphore sem;
u16 listen_intvl_b; u16 listen_intvl_b;
...@@ -662,4 +665,5 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, ...@@ -662,4 +665,5 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
void ath6kl_init_control_info(struct ath6kl_vif *vif); 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);
#endif /* CORE_H */ #endif /* CORE_H */
...@@ -397,15 +397,20 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, ...@@ -397,15 +397,20 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath6kl *ar = file->private_data; struct ath6kl *ar = file->private_data;
/* TODO: Findout vif */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif; struct target_stats *tgt_stats;
struct target_stats *tgt_stats = &vif->target_stats;
char *buf; char *buf;
unsigned int len = 0, buf_len = 1500; unsigned int len = 0, buf_len = 1500;
int i; int i;
long left; long left;
ssize_t ret_cnt; ssize_t ret_cnt;
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
tgt_stats = &vif->target_stats;
buf = kzalloc(buf_len, GFP_KERNEL); buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
...@@ -1249,8 +1254,7 @@ static ssize_t ath6kl_create_qos_write(struct file *file, ...@@ -1249,8 +1254,7 @@ static ssize_t ath6kl_create_qos_write(struct file *file,
{ {
struct ath6kl *ar = file->private_data; struct ath6kl *ar = file->private_data;
/* TODO: Findout vif */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif;
char buf[100]; char buf[100];
ssize_t len; ssize_t len;
char *sptr, *token; char *sptr, *token;
...@@ -1258,6 +1262,10 @@ static ssize_t ath6kl_create_qos_write(struct file *file, ...@@ -1258,6 +1262,10 @@ static ssize_t ath6kl_create_qos_write(struct file *file,
u32 val32; u32 val32;
u16 val16; u16 val16;
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
len = min(count, sizeof(buf) - 1); len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len)) if (copy_from_user(buf, user_buf, len))
return -EFAULT; return -EFAULT;
...@@ -1423,14 +1431,17 @@ static ssize_t ath6kl_delete_qos_write(struct file *file, ...@@ -1423,14 +1431,17 @@ static ssize_t ath6kl_delete_qos_write(struct file *file,
{ {
struct ath6kl *ar = file->private_data; struct ath6kl *ar = file->private_data;
/* TODO: Findout vif */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif;
char buf[100]; char buf[100];
ssize_t len; ssize_t len;
char *sptr, *token; char *sptr, *token;
u8 traffic_class; u8 traffic_class;
u8 tsid; u8 tsid;
vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;
len = min(count, sizeof(buf) - 1); len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len)) if (copy_from_user(buf, user_buf, len))
return -EFAULT; return -EFAULT;
......
...@@ -1628,11 +1628,7 @@ static void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) ...@@ -1628,11 +1628,7 @@ static void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
void ath6kl_stop_txrx(struct ath6kl *ar) void ath6kl_stop_txrx(struct ath6kl *ar)
{ {
struct ath6kl_vif *vif = ar->vif; struct ath6kl_vif *vif, *tmp_vif;
struct net_device *ndev = vif->ndev;
if (!ndev)
return;
set_bit(DESTROY_IN_PROGRESS, &ar->flag); set_bit(DESTROY_IN_PROGRESS, &ar->flag);
...@@ -1641,7 +1637,14 @@ void ath6kl_stop_txrx(struct ath6kl *ar) ...@@ -1641,7 +1637,14 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
return; return;
} }
ath6kl_cleanup_vif(ar->vif, test_bit(WMI_READY, &ar->flag)); spin_lock(&ar->list_lock);
list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
list_del(&vif->list);
spin_unlock(&ar->list_lock);
ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
spin_lock(&ar->list_lock);
}
spin_unlock(&ar->list_lock);
clear_bit(WMI_READY, &ar->flag); clear_bit(WMI_READY, &ar->flag);
......
...@@ -861,8 +861,19 @@ void ath6kl_disconnect(struct ath6kl_vif *vif) ...@@ -861,8 +861,19 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
void ath6kl_deep_sleep_enable(struct ath6kl *ar) void ath6kl_deep_sleep_enable(struct ath6kl *ar)
{ {
/* TODO: Pass vif instead of taking it from ar */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif;
/* FIXME: for multi vif */
vif = ath6kl_vif_first(ar);
if (!vif) {
/* save the current power mode before enabling power save */
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
ath6kl_warn("ath6kl_deep_sleep_enable: "
"wmi_powermode_cmd failed\n");
return;
}
switch (vif->sme_state) { switch (vif->sme_state) {
case SME_CONNECTING: case SME_CONNECTING:
...@@ -1363,6 +1374,23 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, ...@@ -1363,6 +1374,23 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
ath6kl_tx_data_cleanup(ar); ath6kl_tx_data_cleanup(ar);
} }
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
{
struct ath6kl_vif *vif;
spin_lock(&ar->list_lock);
if (list_empty(&ar->vif_list)) {
spin_unlock(&ar->list_lock);
return NULL;
}
vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list);
spin_unlock(&ar->list_lock);
return vif;
}
static int ath6kl_open(struct net_device *dev) static int ath6kl_open(struct net_device *dev)
{ {
struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev);
......
...@@ -432,9 +432,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -432,9 +432,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
struct htc_packet *packet) struct htc_packet *packet)
{ {
struct ath6kl *ar = target->dev->ar; struct ath6kl *ar = target->dev->ar;
/* TODO: Findout vif properly */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif;
enum htc_endpoint_id endpoint = packet->endpoint; enum htc_endpoint_id endpoint = packet->endpoint;
enum htc_send_full_action action = HTC_SEND_FULL_KEEP;
if (endpoint == ar->ctrl_ep) { if (endpoint == ar->ctrl_ep) {
/* /*
...@@ -447,19 +447,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -447,19 +447,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
set_bit(WMI_CTRL_EP_FULL, &ar->flag); set_bit(WMI_CTRL_EP_FULL, &ar->flag);
spin_unlock_bh(&ar->lock); spin_unlock_bh(&ar->lock);
ath6kl_err("wmi ctrl ep is full\n"); ath6kl_err("wmi ctrl ep is full\n");
return HTC_SEND_FULL_KEEP; goto stop_adhoc_netq;
} }
if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG) if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
return HTC_SEND_FULL_KEEP; goto stop_adhoc_netq;
if (vif->nw_type == ADHOC_NETWORK)
/*
* In adhoc mode, we cannot differentiate traffic
* priorities so there is no need to continue, however we
* should stop the network.
*/
goto stop_net_queues;
/* /*
* The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
...@@ -467,28 +459,40 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -467,28 +459,40 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/ */
if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
ar->hiac_stream_active_pri && ar->hiac_stream_active_pri &&
ar->cookie_count <= MAX_HI_COOKIE_NUM) ar->cookie_count <= MAX_HI_COOKIE_NUM) {
/* /*
* Give preference to the highest priority stream by * Give preference to the highest priority stream by
* dropping the packets which overflowed. * dropping the packets which overflowed.
*/ */
return HTC_SEND_FULL_DROP; action = HTC_SEND_FULL_DROP;
goto stop_adhoc_netq;
}
stop_adhoc_netq:
/* FIXME: Locking */
spin_lock(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) {
if (vif->nw_type == ADHOC_NETWORK) {
spin_unlock(&ar->list_lock);
stop_net_queues:
spin_lock_bh(&vif->if_lock); spin_lock_bh(&vif->if_lock);
set_bit(NETQ_STOPPED, &vif->flags); set_bit(NETQ_STOPPED, &vif->flags);
spin_unlock_bh(&vif->if_lock); spin_unlock_bh(&vif->if_lock);
netif_stop_queue(vif->ndev); netif_stop_queue(vif->ndev);
return HTC_SEND_FULL_KEEP; return action;
}
}
spin_unlock(&ar->list_lock);
return action;
} }
/* TODO this needs to be looked at */ /* TODO this needs to be looked at */
static void ath6kl_tx_clear_node_map(struct ath6kl *ar, static void ath6kl_tx_clear_node_map(struct ath6kl_vif *vif,
enum htc_endpoint_id eid, u32 map_no) enum htc_endpoint_id eid, u32 map_no)
{ {
/* TODO: Findout vif */ struct ath6kl *ar = vif->ar;
struct ath6kl_vif *vif = ar->vif;
u32 i; u32 i;
if (vif->nw_type != ADHOC_NETWORK) if (vif->nw_type != ADHOC_NETWORK)
...@@ -533,10 +537,9 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -533,10 +537,9 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
int status; int status;
enum htc_endpoint_id eid; enum htc_endpoint_id eid;
bool wake_event = false; bool wake_event = false;
bool flushing = false; bool flushing[MAX_NUM_VIF] = {false};
u8 if_idx; u8 if_idx;
/* TODO: Findout vif */ struct ath6kl_vif *vif;
struct ath6kl_vif *vif = ar->vif;
skb_queue_head_init(&skb_queue); skb_queue_head_init(&skb_queue);
...@@ -599,7 +602,7 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -599,7 +602,7 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
if (status) { if (status) {
if (status == -ECANCELED) if (status == -ECANCELED)
/* a packet was flushed */ /* a packet was flushed */
flushing = true; flushing[if_idx] = true;
vif->net_stats.tx_errors++; vif->net_stats.tx_errors++;
...@@ -615,12 +618,12 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -615,12 +618,12 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
__func__, skb, packet->buf, packet->act_len, __func__, skb, packet->buf, packet->act_len,
eid, "OK"); eid, "OK");
flushing = false; flushing[if_idx] = false;
vif->net_stats.tx_packets++; vif->net_stats.tx_packets++;
vif->net_stats.tx_bytes += skb->len; vif->net_stats.tx_bytes += skb->len;
} }
ath6kl_tx_clear_node_map(ar, eid, map_no); ath6kl_tx_clear_node_map(vif, eid, map_no);
ath6kl_free_cookie(ar, ath6kl_cookie); ath6kl_free_cookie(ar, ath6kl_cookie);
...@@ -632,10 +635,17 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -632,10 +635,17 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
__skb_queue_purge(&skb_queue); __skb_queue_purge(&skb_queue);
if (test_bit(CONNECTED, &vif->flags)) { /* FIXME: Locking */
if (!flushing) spin_lock(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) {
if (test_bit(CONNECTED, &vif->flags) &&
!flushing[vif->fw_vif_idx]) {
spin_unlock(&ar->list_lock);
netif_wake_queue(vif->ndev); netif_wake_queue(vif->ndev);
spin_lock(&ar->list_lock);
}
} }
spin_unlock(&ar->list_lock);
if (wake_event) if (wake_event)
wake_up(&ar->event_wq); wake_up(&ar->event_wq);
......
...@@ -83,10 +83,22 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi) ...@@ -83,10 +83,22 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi)
struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx) struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
{ {
struct ath6kl_vif *vif, *found = NULL;
if (WARN_ON(if_idx > (MAX_NUM_VIF - 1))) if (WARN_ON(if_idx > (MAX_NUM_VIF - 1)))
return NULL; return NULL;
return ar->vif; /* FIXME: Locking */
spin_lock(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) {
if (vif->fw_vif_idx == if_idx) {
found = vif;
break;
}
}
spin_unlock(&ar->list_lock);
return found;
} }
/* Performs DIX to 802.3 encapsulation for transmit packets. /* Performs DIX to 802.3 encapsulation for transmit packets.
...@@ -2459,7 +2471,7 @@ int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx) ...@@ -2459,7 +2471,7 @@ int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx)
return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_STATISTICS_CMDID); return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_STATISTICS_CMDID);
} }
int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM) int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct wmi_set_tx_pwr_cmd *cmd; struct wmi_set_tx_pwr_cmd *cmd;
...@@ -2472,15 +2484,15 @@ int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM) ...@@ -2472,15 +2484,15 @@ int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
cmd = (struct wmi_set_tx_pwr_cmd *) skb->data; cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
cmd->dbM = dbM; cmd->dbM = dbM;
ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_TX_PWR_CMDID, ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_TX_PWR_CMDID,
NO_SYNC_WMIFLAG); NO_SYNC_WMIFLAG);
return ret; return ret;
} }
int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi) int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx)
{ {
return ath6kl_wmi_simple_cmd(wmi, 0, WMI_GET_TX_PWR_CMDID); return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_TX_PWR_CMDID);
} }
int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi) int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi)
......
...@@ -2258,8 +2258,8 @@ int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk); ...@@ -2258,8 +2258,8 @@ int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index); int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
const u8 *pmkid, bool set); const u8 *pmkid, bool set);
int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM); int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM);
int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi); int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx);
int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi); int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi);
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg); int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
......
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