A few things:

* straggler timer conversions from Kees
  * memory leak fix in hwsim
  * fix some fallout from regdb changes if wireless is built-in
  * also free aggregation sessions in startup state when station
    goes away, to avoid crashing the timer
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAloS/PAACgkQB8qZga/f
 l8SiZQ/+N64u2l8+2MHlAmWPCIsrCVL/jLqNPAmG45ep7mlqYsxnoghXQKw5yKxt
 QodxGE8ixpih39gv3K2coPlRc+3W/C8RXlovGwoU78CCpW5EGcuzqQyh2zNCCY60
 WdKjML7+KF4M3V1hQWvuunpYK97x4UN5wgf5p/e8us/kA/CR9okaIEiG0OzZ9Sb9
 OItQfsWv4zwa+fYnqRHvQ1f2c+niqye9lrygo7HM639l384k4GWToFnZ0Bj4r5mO
 Nmiv9l1aYXcnCIRBTJoYHm9ifL2JwokYpEEAKuhgliOhRA+CyoJCClLDpEvK2NQk
 MWMcegEWDQ10kRiQOyytdO2H2XCX8Qzh8NdNLLggiG4nQgUovqrBcdnUbc9stX3P
 KSZCBcvUdw3aTzs4UFU8HwG0YDnMTXZ+li/pPSad8CUvnRMr6LS/VZ/FIlPuRfLb
 Ha+UraziPoSl0YMFvCCZYZ6wQ1oqWdc+0+67oczMi4KBmUumlN10qg5rEeEi2Ael
 71NO2rOvMv/WYPfztQz8zuiB+g35yXAMOOY0SLFt+vfl0loWB6rRgxFjoo4dhrNv
 5LtVgZiGwvedrgTIvq2CCjJN52PT51RFDzOhIR1NSOoDx3AdyeBKnulYUIED14f3
 xHyOlnDbpW6B4+c0h1Hs5f4d0BMwU/dhLrUD8k4UU+qcdA4/EG8=
 =jcSa
 -----END PGP SIGNATURE-----

Merge tag 'mac80211-for-davem-2017-11-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
A few things:
 * straggler timer conversions from Kees
 * memory leak fix in hwsim
 * fix some fallout from regdb changes if wireless is built-in
 * also free aggregation sessions in startup state when station
   goes away, to avoid crashing the timer
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2017-11-21 20:30:57 +09:00
commit a13e8d418f
17 changed files with 155 additions and 137 deletions

View File

@ -3108,6 +3108,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
{ {
struct hwsim_new_radio_params param = { 0 }; struct hwsim_new_radio_params param = { 0 };
const char *hwname = NULL; const char *hwname = NULL;
int ret;
param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
@ -3147,7 +3148,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
param.regd = hwsim_world_regdom_custom[idx]; param.regd = hwsim_world_regdom_custom[idx];
} }
return mac80211_hwsim_new_radio(info, &param); ret = mac80211_hwsim_new_radio(info, &param);
kfree(hwname);
return ret;
} }
static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)

View File

@ -151,21 +151,17 @@ EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
* After accepting the AddBA Request we activated a timer, * After accepting the AddBA Request we activated a timer,
* resetting it after each frame that arrives from the originator. * resetting it after each frame that arrives from the originator.
*/ */
static void sta_rx_agg_session_timer_expired(unsigned long data) static void sta_rx_agg_session_timer_expired(struct timer_list *t)
{ {
/* not an elegant detour, but there is no choice as the timer passes struct tid_ampdu_rx *tid_rx_timer =
* only one argument, and various sta_info are needed here, so init from_timer(tid_rx_timer, t, session_timer);
* flow in sta_info_create gives the TID as data, while the timer_to_id struct sta_info *sta = tid_rx_timer->sta;
* array gives the sta through container_of */ u8 tid = tid_rx_timer->tid;
u8 *ptid = (u8 *)data;
u8 *timer_to_id = ptid - *ptid;
struct sta_info *sta = container_of(timer_to_id, struct sta_info,
timer_to_tid[0]);
struct tid_ampdu_rx *tid_rx; struct tid_ampdu_rx *tid_rx;
unsigned long timeout; unsigned long timeout;
rcu_read_lock(); rcu_read_lock();
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
if (!tid_rx) { if (!tid_rx) {
rcu_read_unlock(); rcu_read_unlock();
return; return;
@ -180,21 +176,18 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
rcu_read_unlock(); rcu_read_unlock();
ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n", ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
sta->sta.addr, (u16)*ptid); sta->sta.addr, tid);
set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
} }
static void sta_rx_agg_reorder_timer_expired(unsigned long data) static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
{ {
u8 *ptid = (u8 *)data; struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
u8 *timer_to_id = ptid - *ptid;
struct sta_info *sta = container_of(timer_to_id, struct sta_info,
timer_to_tid[0]);
rcu_read_lock(); rcu_read_lock();
ieee80211_release_reorder_timeout(sta, *ptid); ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
rcu_read_unlock(); rcu_read_unlock();
} }
@ -356,14 +349,12 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
spin_lock_init(&tid_agg_rx->reorder_lock); spin_lock_init(&tid_agg_rx->reorder_lock);
/* rx timer */ /* rx timer */
setup_deferrable_timer(&tid_agg_rx->session_timer, timer_setup(&tid_agg_rx->session_timer,
sta_rx_agg_session_timer_expired, sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
(unsigned long)&sta->timer_to_tid[tid]);
/* rx reorder timer */ /* rx reorder timer */
setup_timer(&tid_agg_rx->reorder_timer, timer_setup(&tid_agg_rx->reorder_timer,
sta_rx_agg_reorder_timer_expired, sta_rx_agg_reorder_timer_expired, 0);
(unsigned long)&sta->timer_to_tid[tid]);
/* prepare reordering buffer */ /* prepare reordering buffer */
tid_agg_rx->reorder_buf = tid_agg_rx->reorder_buf =
@ -399,6 +390,8 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
tid_agg_rx->auto_seq = auto_seq; tid_agg_rx->auto_seq = auto_seq;
tid_agg_rx->started = false; tid_agg_rx->started = false;
tid_agg_rx->reorder_buf_filtered = 0; tid_agg_rx->reorder_buf_filtered = 0;
tid_agg_rx->tid = tid;
tid_agg_rx->sta = sta;
status = WLAN_STATUS_SUCCESS; status = WLAN_STATUS_SUCCESS;
/* activate it for RX */ /* activate it for RX */

View File

@ -330,6 +330,11 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
/* free struct pending for start, if present */
tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
kfree(tid_tx);
sta->ampdu_mlme.tid_start_tx[tid] = NULL;
tid_tx = rcu_dereference_protected_tid_tx(sta, tid); tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx) { if (!tid_tx) {
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
@ -422,15 +427,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
* add Block Ack response will arrive from the recipient. * add Block Ack response will arrive from the recipient.
* If this timer expires sta_addba_resp_timer_expired will be executed. * If this timer expires sta_addba_resp_timer_expired will be executed.
*/ */
static void sta_addba_resp_timer_expired(unsigned long data) static void sta_addba_resp_timer_expired(struct timer_list *t)
{ {
/* not an elegant detour, but there is no choice as the timer passes struct tid_ampdu_tx *tid_tx_timer =
* only one argument, and both sta_info and TID are needed, so init from_timer(tid_tx_timer, t, addba_resp_timer);
* flow in sta_info_create gives the TID as data, while the timer_to_id struct sta_info *sta = tid_tx_timer->sta;
* array gives the sta through container_of */ u8 tid = tid_tx_timer->tid;
u16 tid = *(u8 *)data;
struct sta_info *sta = container_of((void *)data,
struct sta_info, timer_to_tid[tid]);
struct tid_ampdu_tx *tid_tx; struct tid_ampdu_tx *tid_tx;
/* check if the TID waits for addBA response */ /* check if the TID waits for addBA response */
@ -525,21 +527,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
* After accepting the AddBA Response we activated a timer, * After accepting the AddBA Response we activated a timer,
* resetting it after each frame that we send. * resetting it after each frame that we send.
*/ */
static void sta_tx_agg_session_timer_expired(unsigned long data) static void sta_tx_agg_session_timer_expired(struct timer_list *t)
{ {
/* not an elegant detour, but there is no choice as the timer passes struct tid_ampdu_tx *tid_tx_timer =
* only one argument, and various sta_info are needed here, so init from_timer(tid_tx_timer, t, session_timer);
* flow in sta_info_create gives the TID as data, while the timer_to_id struct sta_info *sta = tid_tx_timer->sta;
* array gives the sta through container_of */ u8 tid = tid_tx_timer->tid;
u8 *ptid = (u8 *)data;
u8 *timer_to_id = ptid - *ptid;
struct sta_info *sta = container_of(timer_to_id, struct sta_info,
timer_to_tid[0]);
struct tid_ampdu_tx *tid_tx; struct tid_ampdu_tx *tid_tx;
unsigned long timeout; unsigned long timeout;
rcu_read_lock(); rcu_read_lock();
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[*ptid]); tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
if (!tid_tx || test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { if (!tid_tx || test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
rcu_read_unlock(); rcu_read_unlock();
return; return;
@ -555,9 +553,9 @@ static void sta_tx_agg_session_timer_expired(unsigned long data)
rcu_read_unlock(); rcu_read_unlock();
ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n", ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
sta->sta.addr, (u16)*ptid); sta->sta.addr, tid);
ieee80211_stop_tx_ba_session(&sta->sta, *ptid); ieee80211_stop_tx_ba_session(&sta->sta, tid);
} }
int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
@ -670,16 +668,15 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
__set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
tid_tx->timeout = timeout; tid_tx->timeout = timeout;
tid_tx->sta = sta;
tid_tx->tid = tid;
/* response timer */ /* response timer */
setup_timer(&tid_tx->addba_resp_timer, timer_setup(&tid_tx->addba_resp_timer, sta_addba_resp_timer_expired, 0);
sta_addba_resp_timer_expired,
(unsigned long)&sta->timer_to_tid[tid]);
/* tx timer */ /* tx timer */
setup_deferrable_timer(&tid_tx->session_timer, timer_setup(&tid_tx->session_timer,
sta_tx_agg_session_timer_expired, sta_tx_agg_session_timer_expired, TIMER_DEFERRABLE);
(unsigned long)&sta->timer_to_tid[tid]);
/* assign a dialog token */ /* assign a dialog token */
sta->ampdu_mlme.dialog_token_allocator++; sta->ampdu_mlme.dialog_token_allocator++;

View File

@ -1711,10 +1711,10 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
sdata_unlock(sdata); sdata_unlock(sdata);
} }
static void ieee80211_ibss_timer(unsigned long data) static void ieee80211_ibss_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.ibss.timer);
ieee80211_queue_work(&sdata->local->hw, &sdata->work); ieee80211_queue_work(&sdata->local->hw, &sdata->work);
} }
@ -1723,8 +1723,7 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
setup_timer(&ifibss->timer, ieee80211_ibss_timer, timer_setup(&ifibss->timer, ieee80211_ibss_timer, 0);
(unsigned long) sdata);
INIT_LIST_HEAD(&ifibss->incomplete_stations); INIT_LIST_HEAD(&ifibss->incomplete_stations);
spin_lock_init(&ifibss->incomplete_lock); spin_lock_init(&ifibss->incomplete_lock);
INIT_WORK(&ifibss->csa_connection_drop_work, INIT_WORK(&ifibss->csa_connection_drop_work,

View File

@ -1057,6 +1057,7 @@ struct tpt_led_trigger {
const struct ieee80211_tpt_blink *blink_table; const struct ieee80211_tpt_blink *blink_table;
unsigned int blink_table_len; unsigned int blink_table_len;
struct timer_list timer; struct timer_list timer;
struct ieee80211_local *local;
unsigned long prev_traffic; unsigned long prev_traffic;
unsigned long tx_bytes, rx_bytes; unsigned long tx_bytes, rx_bytes;
unsigned int active, want; unsigned int active, want;
@ -1932,7 +1933,7 @@ static inline int ieee80211_ac_from_tid(int tid)
void ieee80211_dynamic_ps_enable_work(struct work_struct *work); void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
void ieee80211_dynamic_ps_disable_work(struct work_struct *work); void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
void ieee80211_dynamic_ps_timer(unsigned long data); void ieee80211_dynamic_ps_timer(struct timer_list *t);
void ieee80211_send_nullfunc(struct ieee80211_local *local, void ieee80211_send_nullfunc(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, struct ieee80211_sub_if_data *sdata,
bool powersave); bool powersave);

View File

@ -248,10 +248,10 @@ static unsigned long tpt_trig_traffic(struct ieee80211_local *local,
return DIV_ROUND_UP(delta, 1024 / 8); return DIV_ROUND_UP(delta, 1024 / 8);
} }
static void tpt_trig_timer(unsigned long data) static void tpt_trig_timer(struct timer_list *t)
{ {
struct ieee80211_local *local = (void *)data; struct tpt_led_trigger *tpt_trig = from_timer(tpt_trig, t, timer);
struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; struct ieee80211_local *local = tpt_trig->local;
struct led_classdev *led_cdev; struct led_classdev *led_cdev;
unsigned long on, off, tpt; unsigned long on, off, tpt;
int i; int i;
@ -306,8 +306,9 @@ __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
tpt_trig->blink_table = blink_table; tpt_trig->blink_table = blink_table;
tpt_trig->blink_table_len = blink_table_len; tpt_trig->blink_table_len = blink_table_len;
tpt_trig->want = flags; tpt_trig->want = flags;
tpt_trig->local = local;
setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); timer_setup(&tpt_trig->timer, tpt_trig_timer, 0);
local->tpt_led_trigger = tpt_trig; local->tpt_led_trigger = tpt_trig;
@ -326,7 +327,7 @@ static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
tpt_trig_traffic(local, tpt_trig); tpt_trig_traffic(local, tpt_trig);
tpt_trig->running = true; tpt_trig->running = true;
tpt_trig_timer((unsigned long)local); tpt_trig_timer(&tpt_trig->timer);
mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
} }

View File

@ -633,8 +633,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
ieee80211_dynamic_ps_enable_work); ieee80211_dynamic_ps_enable_work);
INIT_WORK(&local->dynamic_ps_disable_work, INIT_WORK(&local->dynamic_ps_disable_work,
ieee80211_dynamic_ps_disable_work); ieee80211_dynamic_ps_disable_work);
setup_timer(&local->dynamic_ps_timer, timer_setup(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer, 0);
ieee80211_dynamic_ps_timer, (unsigned long) local);
INIT_WORK(&local->sched_scan_stopped_work, INIT_WORK(&local->sched_scan_stopped_work,
ieee80211_sched_scan_stopped_work); ieee80211_sched_scan_stopped_work);

View File

@ -37,9 +37,10 @@ void ieee80211s_stop(void)
kmem_cache_destroy(rm_cache); kmem_cache_destroy(rm_cache);
} }
static void ieee80211_mesh_housekeeping_timer(unsigned long data) static void ieee80211_mesh_housekeeping_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = (void *) data; struct ieee80211_sub_if_data *sdata =
from_timer(sdata, t, u.mesh.housekeeping_timer);
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@ -528,18 +529,18 @@ int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata,
return 0; return 0;
} }
static void ieee80211_mesh_path_timer(unsigned long data) static void ieee80211_mesh_path_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mesh.mesh_path_timer);
ieee80211_queue_work(&sdata->local->hw, &sdata->work); ieee80211_queue_work(&sdata->local->hw, &sdata->work);
} }
static void ieee80211_mesh_path_root_timer(unsigned long data) static void ieee80211_mesh_path_root_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mesh.mesh_path_root_timer);
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
@ -1442,9 +1443,8 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
static u8 zero_addr[ETH_ALEN] = {}; static u8 zero_addr[ETH_ALEN] = {};
setup_timer(&ifmsh->housekeeping_timer, timer_setup(&ifmsh->housekeeping_timer,
ieee80211_mesh_housekeeping_timer, ieee80211_mesh_housekeeping_timer, 0);
(unsigned long) sdata);
ifmsh->accepting_plinks = true; ifmsh->accepting_plinks = true;
atomic_set(&ifmsh->mpaths, 0); atomic_set(&ifmsh->mpaths, 0);
@ -1458,12 +1458,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
mesh_pathtbl_init(sdata); mesh_pathtbl_init(sdata);
setup_timer(&ifmsh->mesh_path_timer, timer_setup(&ifmsh->mesh_path_timer, ieee80211_mesh_path_timer, 0);
ieee80211_mesh_path_timer, timer_setup(&ifmsh->mesh_path_root_timer,
(unsigned long) sdata); ieee80211_mesh_path_root_timer, 0);
setup_timer(&ifmsh->mesh_path_root_timer,
ieee80211_mesh_path_root_timer,
(unsigned long) sdata);
INIT_LIST_HEAD(&ifmsh->preq_queue.list); INIT_LIST_HEAD(&ifmsh->preq_queue.list);
skb_queue_head_init(&ifmsh->ps.bc_buf); skb_queue_head_init(&ifmsh->ps.bc_buf);
spin_lock_init(&ifmsh->mesh_preq_queue_lock); spin_lock_init(&ifmsh->mesh_preq_queue_lock);

View File

@ -296,7 +296,7 @@ void mesh_path_tx_pending(struct mesh_path *mpath);
int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata); int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata);
void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata); void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata);
int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr);
void mesh_path_timer(unsigned long data); void mesh_path_timer(struct timer_list *t);
void mesh_path_flush_by_nexthop(struct sta_info *sta); void mesh_path_flush_by_nexthop(struct sta_info *sta);
void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb); struct sk_buff *skb);

View File

@ -1194,9 +1194,9 @@ endlookup:
return err; return err;
} }
void mesh_path_timer(unsigned long data) void mesh_path_timer(struct timer_list *t)
{ {
struct mesh_path *mpath = (void *) data; struct mesh_path *mpath = from_timer(mpath, t, timer);
struct ieee80211_sub_if_data *sdata = mpath->sdata; struct ieee80211_sub_if_data *sdata = mpath->sdata;
int ret; int ret;

View File

@ -399,8 +399,7 @@ struct mesh_path *mesh_path_new(struct ieee80211_sub_if_data *sdata,
skb_queue_head_init(&new_mpath->frame_queue); skb_queue_head_init(&new_mpath->frame_queue);
new_mpath->exp_time = jiffies; new_mpath->exp_time = jiffies;
spin_lock_init(&new_mpath->state_lock); spin_lock_init(&new_mpath->state_lock);
setup_timer(&new_mpath->timer, mesh_path_timer, timer_setup(&new_mpath->timer, mesh_path_timer, 0);
(unsigned long) new_mpath);
return new_mpath; return new_mpath;
} }

View File

@ -1066,10 +1066,10 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
} }
EXPORT_SYMBOL(ieee80211_chswitch_done); EXPORT_SYMBOL(ieee80211_chswitch_done);
static void ieee80211_chswitch_timer(unsigned long data) static void ieee80211_chswitch_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mgd.chswitch_timer);
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
} }
@ -1577,9 +1577,9 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
} }
} }
void ieee80211_dynamic_ps_timer(unsigned long data) void ieee80211_dynamic_ps_timer(struct timer_list *t)
{ {
struct ieee80211_local *local = (void *) data; struct ieee80211_local *local = from_timer(local, t, dynamic_ps_timer);
ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work); ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
} }
@ -3711,10 +3711,10 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
sdata_unlock(sdata); sdata_unlock(sdata);
} }
static void ieee80211_sta_timer(unsigned long data) static void ieee80211_sta_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mgd.timer);
ieee80211_queue_work(&sdata->local->hw, &sdata->work); ieee80211_queue_work(&sdata->local->hw, &sdata->work);
} }
@ -3991,10 +3991,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
sdata_unlock(sdata); sdata_unlock(sdata);
} }
static void ieee80211_sta_bcn_mon_timer(unsigned long data) static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mgd.bcn_mon_timer);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
@ -4005,10 +4005,10 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
&sdata->u.mgd.beacon_connection_loss_work); &sdata->u.mgd.beacon_connection_loss_work);
} }
static void ieee80211_sta_conn_mon_timer(unsigned long data) static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data; from_timer(sdata, t, u.mgd.conn_mon_timer);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
@ -4139,14 +4139,10 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work, INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
ieee80211_tdls_peer_del_work); ieee80211_tdls_peer_del_work);
setup_timer(&ifmgd->timer, ieee80211_sta_timer, timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0);
(unsigned long) sdata); timer_setup(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 0);
setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
(unsigned long) sdata); timer_setup(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 0);
setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer,
(unsigned long) sdata);
setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
(unsigned long) sdata);
INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk, INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
ieee80211_sta_handle_tspec_ac_params_wk); ieee80211_sta_handle_tspec_ac_params_wk);

View File

@ -150,9 +150,10 @@ void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
sdata_unlock(sdata); sdata_unlock(sdata);
} }
static void ieee80211_ocb_housekeeping_timer(unsigned long data) static void ieee80211_ocb_housekeeping_timer(struct timer_list *t)
{ {
struct ieee80211_sub_if_data *sdata = (void *)data; struct ieee80211_sub_if_data *sdata =
from_timer(sdata, t, u.ocb.housekeeping_timer);
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_ocb *ifocb = &sdata->u.ocb; struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
@ -165,9 +166,8 @@ void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_ocb *ifocb = &sdata->u.ocb; struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
setup_timer(&ifocb->housekeeping_timer, timer_setup(&ifocb->housekeeping_timer,
ieee80211_ocb_housekeeping_timer, ieee80211_ocb_housekeeping_timer, 0);
(unsigned long)sdata);
INIT_LIST_HEAD(&ifocb->incomplete_stations); INIT_LIST_HEAD(&ifocb->incomplete_stations);
spin_lock_init(&ifocb->incomplete_lock); spin_lock_init(&ifocb->incomplete_lock);
} }

View File

@ -379,14 +379,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
if (sta_prepare_rate_control(local, sta, gfp)) if (sta_prepare_rate_control(local, sta, gfp))
goto free_txq; goto free_txq;
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
/*
* timer_to_tid must be initialized with identity mapping
* to enable session_timer's data differentiation. See
* sta_rx_agg_session_timer_expired for usage.
*/
sta->timer_to_tid[i] = i;
}
for (i = 0; i < IEEE80211_NUM_ACS; i++) { for (i = 0; i < IEEE80211_NUM_ACS; i++) {
skb_queue_head_init(&sta->ps_tx_buf[i]); skb_queue_head_init(&sta->ps_tx_buf[i]);
skb_queue_head_init(&sta->tx_filtered[i]); skb_queue_head_init(&sta->tx_filtered[i]);
@ -1064,9 +1056,9 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
return ret; return ret;
} }
static void sta_info_cleanup(unsigned long data) static void sta_info_cleanup(struct timer_list *t)
{ {
struct ieee80211_local *local = (struct ieee80211_local *) data; struct ieee80211_local *local = from_timer(local, t, sta_cleanup);
struct sta_info *sta; struct sta_info *sta;
bool timer_needed = false; bool timer_needed = false;
@ -1098,8 +1090,7 @@ int sta_info_init(struct ieee80211_local *local)
mutex_init(&local->sta_mtx); mutex_init(&local->sta_mtx);
INIT_LIST_HEAD(&local->sta_list); INIT_LIST_HEAD(&local->sta_list);
setup_timer(&local->sta_cleanup, sta_info_cleanup, timer_setup(&local->sta_cleanup, sta_info_cleanup, 0);
(unsigned long)local);
return 0; return 0;
} }

View File

@ -126,6 +126,8 @@ enum ieee80211_agg_stop_reason {
AGG_STOP_DESTROY_STA, AGG_STOP_DESTROY_STA,
}; };
struct sta_info;
/** /**
* struct tid_ampdu_tx - TID aggregation information (Tx). * struct tid_ampdu_tx - TID aggregation information (Tx).
* *
@ -133,8 +135,10 @@ enum ieee80211_agg_stop_reason {
* @session_timer: check if we keep Tx-ing on the TID (by timeout value) * @session_timer: check if we keep Tx-ing on the TID (by timeout value)
* @addba_resp_timer: timer for peer's response to addba request * @addba_resp_timer: timer for peer's response to addba request
* @pending: pending frames queue -- use sta's spinlock to protect * @pending: pending frames queue -- use sta's spinlock to protect
* @sta: station we are attached to
* @dialog_token: dialog token for aggregation session * @dialog_token: dialog token for aggregation session
* @timeout: session timeout value to be filled in ADDBA requests * @timeout: session timeout value to be filled in ADDBA requests
* @tid: TID number
* @state: session state (see above) * @state: session state (see above)
* @last_tx: jiffies of last tx activity * @last_tx: jiffies of last tx activity
* @stop_initiator: initiator of a session stop * @stop_initiator: initiator of a session stop
@ -158,6 +162,7 @@ struct tid_ampdu_tx {
struct timer_list session_timer; struct timer_list session_timer;
struct timer_list addba_resp_timer; struct timer_list addba_resp_timer;
struct sk_buff_head pending; struct sk_buff_head pending;
struct sta_info *sta;
unsigned long state; unsigned long state;
unsigned long last_tx; unsigned long last_tx;
u16 timeout; u16 timeout;
@ -169,6 +174,7 @@ struct tid_ampdu_tx {
u16 failed_bar_ssn; u16 failed_bar_ssn;
bool bar_pending; bool bar_pending;
bool amsdu; bool amsdu;
u8 tid;
}; };
/** /**
@ -181,12 +187,14 @@ struct tid_ampdu_tx {
* @reorder_time: jiffies when skb was added * @reorder_time: jiffies when skb was added
* @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
* @reorder_timer: releases expired frames from the reorder buffer. * @reorder_timer: releases expired frames from the reorder buffer.
* @sta: station we are attached to
* @last_rx: jiffies of last rx activity * @last_rx: jiffies of last rx activity
* @head_seq_num: head sequence number in reordering buffer. * @head_seq_num: head sequence number in reordering buffer.
* @stored_mpdu_num: number of MPDUs in reordering buffer * @stored_mpdu_num: number of MPDUs in reordering buffer
* @ssn: Starting Sequence Number expected to be aggregated. * @ssn: Starting Sequence Number expected to be aggregated.
* @buf_size: buffer size for incoming A-MPDUs * @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value (in TUs). * @timeout: reset timer value (in TUs).
* @tid: TID number
* @rcu_head: RCU head used for freeing this struct * @rcu_head: RCU head used for freeing this struct
* @reorder_lock: serializes access to reorder buffer, see below. * @reorder_lock: serializes access to reorder buffer, see below.
* @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
@ -208,6 +216,7 @@ struct tid_ampdu_rx {
u64 reorder_buf_filtered; u64 reorder_buf_filtered;
struct sk_buff_head *reorder_buf; struct sk_buff_head *reorder_buf;
unsigned long *reorder_time; unsigned long *reorder_time;
struct sta_info *sta;
struct timer_list session_timer; struct timer_list session_timer;
struct timer_list reorder_timer; struct timer_list reorder_timer;
unsigned long last_rx; unsigned long last_rx;
@ -216,6 +225,7 @@ struct tid_ampdu_rx {
u16 ssn; u16 ssn;
u16 buf_size; u16 buf_size;
u16 timeout; u16 timeout;
u8 tid;
u8 auto_seq:1, u8 auto_seq:1,
removed:1, removed:1,
started:1; started:1;
@ -447,7 +457,6 @@ struct ieee80211_sta_rx_stats {
* plus one for non-QoS frames) * plus one for non-QoS frames)
* @tid_seq: per-TID sequence numbers for sending to this STA * @tid_seq: per-TID sequence numbers for sending to this STA
* @ampdu_mlme: A-MPDU state machine state * @ampdu_mlme: A-MPDU state machine state
* @timer_to_tid: identity mapping to ID timers
* @mesh: mesh STA information * @mesh: mesh STA information
* @debugfs_dir: debug filesystem directory dentry * @debugfs_dir: debug filesystem directory dentry
* @dead: set to true when sta is unlinked * @dead: set to true when sta is unlinked
@ -554,7 +563,6 @@ struct sta_info {
* Aggregation information, locked with lock. * Aggregation information, locked with lock.
*/ */
struct sta_ampdu_mlme ampdu_mlme; struct sta_ampdu_mlme ampdu_mlme;
u8 timer_to_tid[IEEE80211_NUM_TIDS];
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *debugfs_dir; struct dentry *debugfs_dir;

View File

@ -2605,10 +2605,32 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
goto nla_put_failure; goto nla_put_failure;
} }
if (wdev->ssid_len) { wdev_lock(wdev);
if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid)) switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
if (wdev->ssid_len &&
nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
goto nla_put_failure; goto nla_put_failure;
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_ADHOC: {
const u8 *ssid_ie;
if (!wdev->current_bss)
break;
ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
WLAN_EID_SSID);
if (!ssid_ie)
break;
if (nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
goto nla_put_failure;
break;
}
default:
/* nothing */
break;
} }
wdev_unlock(wdev);
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
return 0; return 0;

View File

@ -3644,27 +3644,14 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
} }
} }
int __init regulatory_init(void) static int __init regulatory_init_db(void)
{ {
int err = 0; int err;
err = load_builtin_regdb_keys(); err = load_builtin_regdb_keys();
if (err) if (err)
return err; return err;
reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
if (IS_ERR(reg_pdev))
return PTR_ERR(reg_pdev);
spin_lock_init(&reg_requests_lock);
spin_lock_init(&reg_pending_beacons_lock);
spin_lock_init(&reg_indoor_lock);
rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom);
user_alpha2[0] = '9';
user_alpha2[1] = '7';
/* We always try to get an update for the static regdomain */ /* We always try to get an update for the static regdomain */
err = regulatory_hint_core(cfg80211_world_regdom->alpha2); err = regulatory_hint_core(cfg80211_world_regdom->alpha2);
if (err) { if (err) {
@ -3692,6 +3679,31 @@ int __init regulatory_init(void)
return 0; return 0;
} }
#ifndef MODULE
late_initcall(regulatory_init_db);
#endif
int __init regulatory_init(void)
{
reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
if (IS_ERR(reg_pdev))
return PTR_ERR(reg_pdev);
spin_lock_init(&reg_requests_lock);
spin_lock_init(&reg_pending_beacons_lock);
spin_lock_init(&reg_indoor_lock);
rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom);
user_alpha2[0] = '9';
user_alpha2[1] = '7';
#ifdef MODULE
return regulatory_init_db();
#else
return 0;
#endif
}
void regulatory_exit(void) void regulatory_exit(void)
{ {