Re: [PATCH] d80211: ieee80211_hw handlers should be allowed to sleep
On Wed, 18 Oct 2006 19:27:37 +0200, Ivo van Doorn wrote: Would something like the patch below be better? It keeps the flush_scheduled_work() at the same location, but a second is added in case local-scan_work.data != sdata-dev Applied to my tree, thanks for the patch! Jiri -- Jiri Benc SUSE Labs - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] d80211: ieee80211_hw handlers should be allowed to sleep
On Sat, 7 Oct 2006 11:23:15 +0200, Ivo van Doorn wrote: --- a/net/d80211/ieee80211.c +++ b/net/d80211/ieee80211.c @@ -2075,15 +2075,15 @@ void ieee80211_if_shutdown(struct net_de case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata-u.sta.state = IEEE80211_DISABLED; - del_timer_sync(sdata-u.sta.timer); + cancel_delayed_work(sdata-u.sta.work); if (local-scan_work.data == sdata-dev) { local-sta_scanning = 0; cancel_delayed_work(local-scan_work); - flush_scheduled_work(); /* see comment in ieee80211_unregister_hw to * understand why this works */ local-scan_work.data = NULL; } + flush_scheduled_work(); This is racy. local-scan_work.data can be set to NULL only after flush_scheduled_work(). Other than that, the patch looks good to me. Thanks, Jiri -- Jiri Benc SUSE Labs - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] d80211: ieee80211_hw handlers should be allowed to sleep
On Wednesday 18 October 2006 15:06, Jiri Benc wrote: On Sat, 7 Oct 2006 11:23:15 +0200, Ivo van Doorn wrote: --- a/net/d80211/ieee80211.c +++ b/net/d80211/ieee80211.c @@ -2075,15 +2075,15 @@ void ieee80211_if_shutdown(struct net_de case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata-u.sta.state = IEEE80211_DISABLED; - del_timer_sync(sdata-u.sta.timer); + cancel_delayed_work(sdata-u.sta.work); if (local-scan_work.data == sdata-dev) { local-sta_scanning = 0; cancel_delayed_work(local-scan_work); - flush_scheduled_work(); /* see comment in ieee80211_unregister_hw to * understand why this works */ local-scan_work.data = NULL; } + flush_scheduled_work(); This is racy. local-scan_work.data can be set to NULL only after flush_scheduled_work(). Would something like the patch below be better? It keeps the flush_scheduled_work() at the same location, but a second is added in case local-scan_work.data != sdata-dev Jan, was there any particular reason to move flush_cheduled_work() outside of the if-statement? Signed-off-by Ivo van Doorn [EMAIL PROTECTED] --- diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c index 32a1ba7..cb1180c 100644 --- a/net/d80211/ieee80211.c +++ b/net/d80211/ieee80211.c @@ -2075,7 +2075,7 @@ void ieee80211_if_shutdown(struct net_de case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata-u.sta.state = IEEE80211_DISABLED; - del_timer_sync(sdata-u.sta.timer); + cancel_delayed_work(sdata-u.sta.work); if (local-scan_work.data == sdata-dev) { local-sta_scanning = 0; cancel_delayed_work(local-scan_work); @@ -2083,7 +2083,8 @@ void ieee80211_if_shutdown(struct net_de /* see comment in ieee80211_unregister_hw to * understand why this works */ local-scan_work.data = NULL; - } + } else + flush_scheduled_work(); break; } } @@ -4605,8 +4606,8 @@ void ieee80211_unregister_hw(struct net_ flush_scheduled_work(); /* The scan_work is guaranteed not to be called at this * point. It is not scheduled and not running now. It can be -* scheduled again only by some sta_timer (all of them are -* stopped by now) or under rtnl lock. */ +* scheduled again only by sta_work (stopped by now) or under +* rtnl lock. */ } ieee80211_rx_bss_list_deinit(dev); diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h index 89666ec..5b48ce2 100644 --- a/net/d80211/ieee80211_i.h +++ b/net/d80211/ieee80211_i.h @@ -240,7 +240,7 @@ struct ieee80211_if_sta { IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED } state; - struct timer_list timer; + struct work_struct work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; size_t ssid_len; @@ -621,7 +621,7 @@ int ieee80211_set_compression(struct iee struct net_device *dev, struct sta_info *sta); int ieee80211_init_client(struct net_device *dev); /* ieee80211_sta.c */ -void ieee80211_sta_timer(unsigned long ptr); +void ieee80211_sta_work(void *ptr); void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c index 9a187af..4dd480f 100644 --- a/net/d80211/ieee80211_iface.c +++ b/net/d80211/ieee80211_iface.c @@ -194,9 +194,7 @@ void ieee80211_if_set_type(struct net_de struct ieee80211_if_sta *ifsta; ifsta = sdata-u.sta; - init_timer(ifsta-timer); - ifsta-timer.data = (unsigned long) dev; - ifsta-timer.function = ieee80211_sta_timer; + INIT_WORK(ifsta-work, ieee80211_sta_work, dev); ifsta-capab = WLAN_CAPABILITY_ESS; ifsta-auth_algs = IEEE80211_AUTH_ALG_OPEN | diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c index cc336bd..bf74b6b 100644 --- a/net/d80211/ieee80211_sta.c +++ b/net/d80211/ieee80211_sta.c @@ -457,7 +457,7 @@ static void ieee80211_authenticate(struc ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); - mod_timer(ifsta-timer, jiffies + IEEE80211_AUTH_TIMEOUT); + schedule_delayed_work(ifsta-work, IEEE80211_AUTH_TIMEOUT); } @@ -677,7 +677,7 @@ static void
Re: [PATCH] d80211: ieee80211_hw handlers should be allowed to sleep
Ivo van Doorn wrote: On Wednesday 18 October 2006 15:06, Jiri Benc wrote: On Sat, 7 Oct 2006 11:23:15 +0200, Ivo van Doorn wrote: --- a/net/d80211/ieee80211.c +++ b/net/d80211/ieee80211.c @@ -2075,15 +2075,15 @@ void ieee80211_if_shutdown(struct net_de case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata-u.sta.state = IEEE80211_DISABLED; - del_timer_sync(sdata-u.sta.timer); + cancel_delayed_work(sdata-u.sta.work); if (local-scan_work.data == sdata-dev) { local-sta_scanning = 0; cancel_delayed_work(local-scan_work); - flush_scheduled_work(); /* see comment in ieee80211_unregister_hw to * understand why this works */ local-scan_work.data = NULL; } + flush_scheduled_work(); This is racy. local-scan_work.data can be set to NULL only after flush_scheduled_work(). Would something like the patch below be better? It keeps the flush_scheduled_work() at the same location, but a second is added in case local-scan_work.data != sdata-dev Jan, was there any particular reason to move flush_cheduled_work() outside of the if-statement? It is needed unconditionally now, so I moved it out without knowing about this side effect. Your approach looks good to me. Signed-off-by Ivo van Doorn [EMAIL PROTECTED] --- diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c index 32a1ba7..cb1180c 100644 --- a/net/d80211/ieee80211.c +++ b/net/d80211/ieee80211.c @@ -2075,7 +2075,7 @@ void ieee80211_if_shutdown(struct net_de case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata-u.sta.state = IEEE80211_DISABLED; - del_timer_sync(sdata-u.sta.timer); + cancel_delayed_work(sdata-u.sta.work); if (local-scan_work.data == sdata-dev) { local-sta_scanning = 0; cancel_delayed_work(local-scan_work); @@ -2083,7 +2083,8 @@ void ieee80211_if_shutdown(struct net_de /* see comment in ieee80211_unregister_hw to * understand why this works */ local-scan_work.data = NULL; - } + } else + flush_scheduled_work(); break; } } @@ -4605,8 +4606,8 @@ void ieee80211_unregister_hw(struct net_ flush_scheduled_work(); /* The scan_work is guaranteed not to be called at this * point. It is not scheduled and not running now. It can be - * scheduled again only by some sta_timer (all of them are - * stopped by now) or under rtnl lock. */ + * scheduled again only by sta_work (stopped by now) or under + * rtnl lock. */ } ieee80211_rx_bss_list_deinit(dev); diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h index 89666ec..5b48ce2 100644 --- a/net/d80211/ieee80211_i.h +++ b/net/d80211/ieee80211_i.h @@ -240,7 +240,7 @@ struct ieee80211_if_sta { IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED } state; - struct timer_list timer; + struct work_struct work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; size_t ssid_len; @@ -621,7 +621,7 @@ int ieee80211_set_compression(struct iee struct net_device *dev, struct sta_info *sta); int ieee80211_init_client(struct net_device *dev); /* ieee80211_sta.c */ -void ieee80211_sta_timer(unsigned long ptr); +void ieee80211_sta_work(void *ptr); void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c index 9a187af..4dd480f 100644 --- a/net/d80211/ieee80211_iface.c +++ b/net/d80211/ieee80211_iface.c @@ -194,9 +194,7 @@ void ieee80211_if_set_type(struct net_de struct ieee80211_if_sta *ifsta; ifsta = sdata-u.sta; - init_timer(ifsta-timer); - ifsta-timer.data = (unsigned long) dev; - ifsta-timer.function = ieee80211_sta_timer; + INIT_WORK(ifsta-work, ieee80211_sta_work, dev); ifsta-capab = WLAN_CAPABILITY_ESS; ifsta-auth_algs = IEEE80211_AUTH_ALG_OPEN | diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c index cc336bd..bf74b6b 100644 --- a/net/d80211/ieee80211_sta.c +++ b/net/d80211/ieee80211_sta.c @@ -457,7 +457,7 @@ static void ieee80211_authenticate(struc ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); - mod_timer(ifsta-timer, jiffies +