From 6e28fbef0f330d7c1cade345eeae003d4e5d6070 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 31 Jul 2008 10:53:57 -0300 Subject: rfkill: query EV_SW states when rfkill-input (re)?connects to a input device Every time a new input device that is capable of one of the rfkill EV_SW events (currently only SW_RFKILL_ALL) is connected to rfkill-input, we must check the states of the input EV_SW switches and take action. Otherwise, we will ignore the initial switch state. We also need to re-check the states of the EV_SW switches after a device that was under an exclusive grab is released back to us, since we got no input events from that device while it was grabbed. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Ivo van Doorn Cc: Dmitry Torokhov Signed-off-by: John W. Linville --- net/rfkill/rfkill-input.c | 54 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index 8aa8227..e5b6955 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); +static void rfkill_schedule_evsw_rfkillall(int state) +{ + /* EVERY radio type. state != 0 means radios ON */ + /* handle EPO (emergency power off) through shortcut */ + if (state) { + rfkill_schedule_set(&rfkill_wwan, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_wimax, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_uwb, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_bt, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_wlan, + RFKILL_STATE_UNBLOCKED); + } else + rfkill_schedule_epo(); +} + static void rfkill_event(struct input_handle *handle, unsigned int type, unsigned int code, int data) { @@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, } else if (type == EV_SW) { switch (code) { case SW_RFKILL_ALL: - /* EVERY radio type. data != 0 means radios ON */ - /* handle EPO (emergency power off) through shortcut */ - if (data) { - rfkill_schedule_set(&rfkill_wwan, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wimax, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_uwb, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_bt, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wlan, - RFKILL_STATE_UNBLOCKED); - } else - rfkill_schedule_epo(); + rfkill_schedule_evsw_rfkillall(data); break; default: break; @@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, handle->handler = handler; handle->name = "rfkill"; + /* causes rfkill_start() to be called */ error = input_register_handle(handle); if (error) goto err_free_handle; @@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, return error; } +static void rfkill_start(struct input_handle *handle) +{ + /* Take event_lock to guard against configuration changes, we + * should be able to deal with concurrency with rfkill_event() + * just fine (which event_lock will also avoid). */ + spin_lock_irq(&handle->dev->event_lock); + + if (test_bit(EV_SW, handle->dev->evbit)) { + if (test_bit(SW_RFKILL_ALL, handle->dev->swbit)) + rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL, + handle->dev->sw)); + /* add resync for further EV_SW events here */ + } + + spin_unlock_irq(&handle->dev->event_lock); +} + static void rfkill_disconnect(struct input_handle *handle) { input_close_device(handle); @@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = { .event = rfkill_event, .connect = rfkill_connect, .disconnect = rfkill_disconnect, + .start = rfkill_start, .name = "rfkill", .id_table = rfkill_ids, }; -- cgit v1.1 From 7c4f4578fc85d42d149f86b47f76c28626a20d92 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Jul 2008 14:17:37 +0400 Subject: RFKILL: allow one to specify led trigger name Allow the rfkill driver to specify led trigger name. By default it still defaults to the name of rfkill switch. Signed-off-by: Dmitry Baryshkov Acked-by: Henrique de Moraes Holschuh Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index c6f2f38..5c24f36 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -589,7 +589,8 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) #ifdef CONFIG_RFKILL_LEDS int error; - rfkill->led_trigger.name = rfkill->dev.bus_id; + if (!rfkill->led_trigger.name) + rfkill->led_trigger.name = rfkill->dev.bus_id; error = led_trigger_register(&rfkill->led_trigger); if (error) rfkill->led_trigger.name = NULL; -- cgit v1.1 From 96185664f10e79d038c084305d3cacff9b52204f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Jul 2008 14:21:59 +0400 Subject: RFKILL: set the status of the leds on activation. Provide default activate function to set the state of the led when the led becomes bound to the trigger Signed-off-by: Dmitry Baryshkov Acked-by: Ivo van Doorn Acked-by: Henrique de Moraes Holschuh Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'net') diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 5c24f36..d2d4565 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -105,6 +105,16 @@ static void rfkill_led_trigger(struct rfkill *rfkill, #endif /* CONFIG_RFKILL_LEDS */ } +#ifdef CONFIG_RFKILL_LEDS +static void rfkill_led_trigger_activate(struct led_classdev *led) +{ + struct rfkill *rfkill = container_of(led->trigger, + struct rfkill, led_trigger); + + rfkill_led_trigger(rfkill, rfkill->state); +} +#endif /* CONFIG_RFKILL_LEDS */ + static void notify_rfkill_state_change(struct rfkill *rfkill) { blocking_notifier_call_chain(&rfkill_notifier_list, @@ -591,6 +601,8 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) if (!rfkill->led_trigger.name) rfkill->led_trigger.name = rfkill->dev.bus_id; + if (!rfkill->led_trigger.activate) + rfkill->led_trigger.activate = rfkill_led_trigger_activate; error = led_trigger_register(&rfkill->led_trigger); if (error) rfkill->led_trigger.name = NULL; -- cgit v1.1 From f8e79ddd31c3615ddca26b9a469c44a7adbd4e13 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 24 Jul 2008 18:46:44 +0300 Subject: mac80211: fix fragmentation kludge This patch make mac80211 transmit correctly fragmented packet after queue was stopped Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/tx.c | 17 ++++++++++++----- net/mac80211/util.c | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a4f9a83..a2e200f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -586,6 +586,7 @@ struct ieee80211_local { struct timer_list sta_cleanup; unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; + unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; struct tasklet_struct tx_pending_tasklet; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 69019e9..771ec68 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_tx_data *tx) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; int ret, i; - if (netif_subqueue_stopped(local->mdev, skb)) - return IEEE80211_TX_AGAIN; - if (skb) { + if (netif_subqueue_stopped(local->mdev, skb)) + return IEEE80211_TX_AGAIN; + info = IEEE80211_SKB_CB(skb); + ieee80211_dump_frame(wiphy_name(local->hw.wiphy), "TX to low-level driver", skb); ret = local->ops->tx(local_to_hw(local), skb); @@ -1215,6 +1216,7 @@ retry: if (ret == IEEE80211_TX_FRAG_AGAIN) skb = NULL; + set_bit(queue, local->queues_pending); smp_mb(); /* @@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data) netif_tx_lock_bh(dev); for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { /* Check that this queue is ok */ - if (__netif_subqueue_stopped(local->mdev, i)) + if (__netif_subqueue_stopped(local->mdev, i) && + !test_bit(i, local->queues_pending_run)) continue; if (!test_bit(i, local->queues_pending)) { + clear_bit(i, local->queues_pending_run); ieee80211_wake_queue(&local->hw, i); continue; } + clear_bit(i, local->queues_pending_run); + netif_start_subqueue(local->mdev, i); + store = &local->pending_packet[i]; tx.extra_frag = store->extra_frag; tx.num_extra_frag = store->num_extra_frag; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 19f85e1..0d463c8 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) struct ieee80211_local *local = hw_to_local(hw); if (test_bit(queue, local->queues_pending)) { + set_bit(queue, local->queues_pending_run); tasklet_schedule(&local->tx_pending_tasklet); } else { netif_wake_subqueue(local->mdev, queue); -- cgit v1.1