From 4d1d49858c0a5a4fb1be4bc7972754cd640245ba Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 4 Jun 2009 21:57:03 +0200 Subject: net/libertas: remove GPIO-CS handling in SPI interface code This removes the dependency on GPIO framework and lets the SPI host driver handle the chip select. The SPI host driver is required to keep the CS active for the entire message unless cs_change says otherwise. This patch collects the two/three single SPI transfers into a message. Also the delay in read path in case use_dummy_writes are not used is moved into the SPI host driver. Tested-by: Mike Rapoport Tested-by: Andrey Yurovsky Signed-off-by: Sebastian Andrzej Siewior Acked-by: Dan Williams Signed-off-by: John W. Linville --- include/linux/spi/libertas_spi.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h index 79506f5f9e67..1b5d5384fcd3 100644 --- a/include/linux/spi/libertas_spi.h +++ b/include/linux/spi/libertas_spi.h @@ -22,9 +22,6 @@ struct libertas_spi_platform_data { * speed, you may want to use 0 here. */ u16 use_dummy_writes; - /* GPIO number to use as chip select */ - u16 gpio_cs; - /* Board specific setup/teardown */ int (*setup)(struct spi_device *spi); int (*teardown)(struct spi_device *spi); -- cgit v1.2.3 From 8f77f3849cc3ae2d6df9301785a3d316ea7d7ee1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 7 Jun 2009 21:58:37 +0200 Subject: mac80211: do not pass PS frames out of mac80211 again In order to handle powersave frames properly we had needed to pass these out to the device queues again, and introduce the skb->requeue bit. This, however, also has unnecessary overhead by needing to 'clean up' already tried frames, and this clean-up code is also buggy when software encryption is used. Instead of sending the frames via the master netdev queue again, simply put them into the pending queue. This also fixes a problem where frames for that particular station could be reordered when some were still on the software queues and older ones are re-injected into the software queue after them. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/skbuff.h | 4 --- include/net/mac80211.h | 3 +++ net/core/skbuff.c | 1 - net/mac80211/ieee80211_i.h | 5 ++++ net/mac80211/main.c | 61 +++++----------------------------------------- net/mac80211/rx.c | 25 +++++++------------ net/mac80211/tx.c | 3 ++- net/mac80211/util.c | 46 ++++++++++++++++++++++++++++++++++ net/mac80211/wme.c | 2 +- 9 files changed, 72 insertions(+), 78 deletions(-) (limited to 'include') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f1c93b878b3b..fa51293f2708 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -304,9 +304,6 @@ typedef unsigned char *sk_buff_data_t; * @tc_verd: traffic control verdict * @ndisc_nodetype: router type (from link layer) * @do_not_encrypt: set to prevent encryption of this frame - * @requeue: set to indicate that the wireless core should attempt - * a software retry on this frame if we failed to - * receive an ACK for it * @dma_cookie: a cookie to one of several possible DMA operations * done by skb DMA functions * @secmark: security marking @@ -380,7 +377,6 @@ struct sk_buff { #endif #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) __u8 do_not_encrypt:1; - __u8 requeue:1; #endif /* 0/13/14 bit hole */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 17d61d19d912..c06104476973 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -239,6 +239,8 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, * used to indicate that a pending frame requires TX processing before * it can be sent out. + * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, + * used to indicate that a frame was already retried due to PS */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -256,6 +258,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), IEEE80211_TX_INTFL_RCALGO = BIT(13), IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), + IEEE80211_TX_INTFL_RETRIED = BIT(15), }; /** diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 49961ba3c0f6..b94d777e3eb4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -552,7 +552,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->vlan_tci = old->vlan_tci; #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) new->do_not_encrypt = old->do_not_encrypt; - new->requeue = old->requeue; #endif skb_copy_secmark(new, old); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c088c46704a3..4dbc28964196 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -589,6 +589,7 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_AGGREGATION, IEEE80211_QUEUE_STOP_REASON_SUSPEND, IEEE80211_QUEUE_STOP_REASON_PENDING, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD, }; struct ieee80211_master_priv { @@ -1121,6 +1122,10 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); +void ieee80211_add_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb); +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs); void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 2683df918073..092a017b237e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -369,60 +369,12 @@ static void ieee80211_tasklet_handler(unsigned long data) } } -/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to - * make a prepared TX frame (one that has been given to hw) to look like brand - * new IEEE 802.11 frame that is ready to go through TX processing again. - */ -static void ieee80211_remove_tx_extra(struct ieee80211_local *local, - struct ieee80211_key *key, - struct sk_buff *skb) -{ - unsigned int hdrlen, iv_len, mic_len; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - - if (!key) - goto no_key; - - switch (key->conf.alg) { - case ALG_WEP: - iv_len = WEP_IV_LEN; - mic_len = WEP_ICV_LEN; - break; - case ALG_TKIP: - iv_len = TKIP_IV_LEN; - mic_len = TKIP_ICV_LEN; - break; - case ALG_CCMP: - iv_len = CCMP_HDR_LEN; - mic_len = CCMP_MIC_LEN; - break; - default: - goto no_key; - } - - if (skb->len >= hdrlen + mic_len && - !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) - skb_trim(skb, skb->len - mic_len); - if (skb->len >= hdrlen + iv_len) { - memmove(skb->data + iv_len, skb->data, hdrlen); - hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); - } - -no_key: - if (ieee80211_is_data_qos(hdr->frame_control)) { - hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); - memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, - hdrlen - IEEE80211_QOS_CTL_LEN); - skb_pull(skb, IEEE80211_QOS_CTL_LEN); - } -} - static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, struct sta_info *sta, struct sk_buff *skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + sta->tx_filtered_count++; /* @@ -464,16 +416,15 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, */ if (test_sta_flags(sta, WLAN_STA_PS) && skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { - ieee80211_remove_tx_extra(local, sta->key, skb); skb_queue_tail(&sta->tx_filtered, skb); return; } - if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { + if (!test_sta_flags(sta, WLAN_STA_PS) && + !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { /* Software retry the packet once */ - skb->requeue = 1; - ieee80211_remove_tx_extra(local, sta->key, skb); - dev_queue_xmit(skb); + info->flags |= IEEE80211_TX_INTFL_RETRIED; + ieee80211_add_pending_skb(local, skb); return; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 754125185109..de5bba7f910a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -797,8 +797,7 @@ static int ap_sta_ps_end(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - int sent = 0; + int sent, buffered; atomic_dec(&sdata->bss->num_sta_ps); @@ -814,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta) #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - sent++; - skb->requeue = 1; - dev_queue_xmit(skb); - } - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - sent++; + sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); + buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); + sent += buffered; + local->total_ps_buffered -= buffered; + #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " - "since STA not sleeping anymore\n", sdata->dev->name, - sta->sta.addr, sta->sta.aid); + printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " + "since STA not sleeping anymore\n", sdata->dev->name, + sta->sta.addr, sta->sta.aid, sent - buffered, buffered); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - skb->requeue = 1; - dev_queue_xmit(skb); - } return sent; } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1436f747531a..bfaa9ce33146 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) sta_info_set_tim_bit(sta); info->control.jiffies = jiffies; + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; skb_queue_tail(&sta->ps_tx_buf, tx->skb); return TX_QUEUED; } @@ -420,7 +421,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) * frame filtering and keeps a station blacklist on its own * (e.g: p54), so that frames can be delivered unimpeded. * - * Note: It should be save to disable the filter now. + * Note: It should be safe to disable the filter now. * As, it is really unlikely that we still have any pending * frame for this station in the hw's buffers/fifos left, * that is not rejected with a unsuccessful tx_status yet. diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22f63815fb36..66ce96a69f31 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -341,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) } EXPORT_SYMBOL(ieee80211_stop_queue); +void ieee80211_add_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb) +{ + struct ieee80211_hw *hw = &local->hw; + unsigned long flags; + int queue = skb_get_queue_mapping(skb); + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING); + skb_queue_tail(&local->pending[queue], skb); + __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +} + +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs) +{ + struct ieee80211_hw *hw = &local->hw; + struct sk_buff *skb; + unsigned long flags; + int queue, ret = 0, i; + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (i = 0; i < hw->queues; i++) + __ieee80211_stop_queue(hw, i, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + + while ((skb = skb_dequeue(skbs))) { + ret++; + queue = skb_get_queue_mapping(skb); + skb_queue_tail(&local->pending[queue], skb); + } + + for (i = 0; i < hw->queues; i++) { + if (ret) + __ieee80211_stop_queue(hw, i, + IEEE80211_QUEUE_STOP_REASON_PENDING); + __ieee80211_wake_queue(hw, i, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + return ret; +} + void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason) { diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 694343b9102b..116a923b14d6 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -101,7 +101,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) * Now we know the 1d priority, fill in the QoS header if * there is one (and we haven't done this before). */ - if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) { + if (ieee80211_is_data_qos(hdr->frame_control)) { u8 *p = ieee80211_get_qos_ctl(hdr); u8 ack_policy = 0; tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; -- cgit v1.2.3 From b3fa1329eaf2a7b97124dacf5b663fd51346ac19 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Mon, 8 Jun 2009 13:27:27 +0100 Subject: rfkill: remove set_global_sw_state rfkill_set_global_sw_state() (previously rfkill_set_default()) will no longer be exported by the rewritten rfkill core. Instead, platform drivers which can provide persistent soft-rfkill state across power-down/reboot should indicate their initial state by calling rfkill_set_sw_state() before registration. Otherwise, they will be initialized to a default value during registration by a set_block call. We remove existing calls to rfkill_set_sw_state() which happen before registration, since these had no effect in the old model. If these drivers do have persistent state, the calls can be put back (subject to testing :-). This affects hp-wmi and acer-wmi. Drivers with persistent state will affect the global state only if rfkill-input is enabled. This is required, otherwise booting with wireless soft-blocked and pressing the wireless-toggle key once would have no apparent effect. This special case will be removed in future along with rfkill-input, in favour of a more flexible userspace daemon (see Documentation/feature-removal-schedule.txt). Now rfkill_global_states[n].def is only used to preserve global states over EPO, it is renamed to ".sav". Signed-off-by: Alan Jenkins Acked-by: Henrique de Moraes Holschuh Signed-off-by: John W. Linville --- drivers/platform/x86/acer-wmi.c | 3 -- drivers/platform/x86/eeepc-laptop.c | 8 ++-- drivers/platform/x86/hp-wmi.c | 4 -- drivers/platform/x86/thinkpad_acpi.c | 31 +++++++------- include/linux/rfkill.h | 28 ++++--------- net/rfkill/core.c | 81 +++++++++++++----------------------- 6 files changed, 56 insertions(+), 99 deletions(-) (limited to 'include') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index b618fa51db2d..09a503e5da6a 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -988,7 +988,6 @@ static struct rfkill *acer_rfkill_register(struct device *dev, char *name, u32 cap) { int err; - u32 state; struct rfkill *rfkill_dev; rfkill_dev = rfkill_alloc(name, dev, type, @@ -996,8 +995,6 @@ static struct rfkill *acer_rfkill_register(struct device *dev, (void *)(unsigned long)cap); if (!rfkill_dev) return ERR_PTR(-ENOMEM); - get_u32(&state, cap); - rfkill_set_sw_state(rfkill_dev, !state); err = rfkill_register(rfkill_dev); if (err) { diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 1208d0cedd15..03bf522bd7ab 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -675,8 +675,8 @@ static int eeepc_hotk_add(struct acpi_device *device) if (!ehotk->eeepc_wlan_rfkill) goto wlan_fail; - rfkill_set_global_sw_state(RFKILL_TYPE_WLAN, - get_acpi(CM_ASL_WLAN) != 1); + rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, + get_acpi(CM_ASL_WLAN) != 1); result = rfkill_register(ehotk->eeepc_wlan_rfkill); if (result) goto wlan_fail; @@ -693,8 +693,8 @@ static int eeepc_hotk_add(struct acpi_device *device) if (!ehotk->eeepc_bluetooth_rfkill) goto bluetooth_fail; - rfkill_set_global_sw_state(RFKILL_TYPE_BLUETOOTH, - get_acpi(CM_ASL_BLUETOOTH) != 1); + rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, + get_acpi(CM_ASL_BLUETOOTH) != 1); result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); if (result) goto bluetooth_fail; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8d931145cbfa..16fffe44e333 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -422,7 +422,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) RFKILL_TYPE_WLAN, &hp_wmi_rfkill_ops, (void *) 0); - rfkill_set_sw_state(wifi_rfkill, hp_wmi_wifi_state()); err = rfkill_register(wifi_rfkill); if (err) goto register_wifi_error; @@ -433,8 +432,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) RFKILL_TYPE_BLUETOOTH, &hp_wmi_rfkill_ops, (void *) 1); - rfkill_set_sw_state(bluetooth_rfkill, - hp_wmi_bluetooth_state()); err = rfkill_register(bluetooth_rfkill); if (err) goto register_bluetooth_error; @@ -445,7 +442,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) RFKILL_TYPE_WWAN, &hp_wmi_rfkill_ops, (void *) 2); - rfkill_set_sw_state(wwan_rfkill, hp_wmi_wwan_state()); err = rfkill_register(wwan_rfkill); if (err) goto register_wwan_err; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index cfcafa4e9473..86e958539f46 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1168,21 +1168,6 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); - initial_sw_status = (tp_rfkops->get_status)(); - if (initial_sw_status < 0) { - printk(TPACPI_ERR - "failed to read initial state for %s, error %d; " - "will turn radio off\n", name, initial_sw_status); - } else { - initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); - if (set_default) { - /* try to set the initial state as the default for the - * rfkill type, since we ask the firmware to preserve - * it across S5 in NVRAM */ - rfkill_set_global_sw_state(rfktype, initial_sw_state); - } - } - atp_rfk = kzalloc(sizeof(struct tpacpi_rfk), GFP_KERNEL); if (atp_rfk) atp_rfk->rfkill = rfkill_alloc(name, @@ -1200,8 +1185,20 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, atp_rfk->id = id; atp_rfk->ops = tp_rfkops; - rfkill_set_states(atp_rfk->rfkill, initial_sw_state, - tpacpi_rfk_check_hwblock_state()); + initial_sw_status = (tp_rfkops->get_status)(); + if (initial_sw_status < 0) { + printk(TPACPI_ERR + "failed to read initial state for %s, error %d\n", + name, initial_sw_status); + } else { + initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); + if (set_default) { + /* try to keep the initial state, since we ask the + * firmware to preserve it across S5 in NVRAM */ + rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state); + } + } + rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); res = rfkill_register(atp_rfk->rfkill); if (res < 0) { diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index d7e818ad0bc4..c1dca0b8138b 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -157,8 +157,14 @@ struct rfkill * __must_check rfkill_alloc(const char *name, * @rfkill: rfkill structure to be registered * * This function should be called by the transmitter driver to register - * the rfkill structure needs to be registered. Before calling this function - * the driver needs to be ready to service method calls from rfkill. + * the rfkill structure. Before calling this function the driver needs + * to be ready to service method calls from rfkill. + * + * If the software blocked state is not set before registration, + * set_block will be called to initialize it to a default value. + * + * If the hardware blocked state is not set before registration, + * it is assumed to be unblocked. */ int __must_check rfkill_register(struct rfkill *rfkill); @@ -250,19 +256,6 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); */ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw); -/** - * rfkill_set_global_sw_state - set global sw block default - * @type: rfkill type to set default for - * @blocked: default to set - * - * This function sets the global default -- use at boot if your platform has - * an rfkill switch. If not early enough this call may be ignored. - * - * XXX: instead of ignoring -- how about just updating all currently - * registered drivers? - */ -void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked); - /** * rfkill_blocked - query rfkill block * @@ -317,11 +310,6 @@ static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) { } -static inline void rfkill_set_global_sw_state(const enum rfkill_type type, - bool blocked) -{ -} - static inline bool rfkill_blocked(struct rfkill *rfkill) { return false; diff --git a/net/rfkill/core.c b/net/rfkill/core.c index e161ebc40a35..fa430bd03f14 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -57,6 +57,7 @@ struct rfkill { bool registered; bool suspended; + bool persistent; const struct rfkill_ops *ops; void *data; @@ -116,11 +117,9 @@ MODULE_PARM_DESC(default_state, "Default initial state for all radio types, 0 = radio off"); static struct { - bool cur, def; + bool cur, sav; } rfkill_global_states[NUM_RFKILL_TYPES]; -static unsigned long rfkill_states_default_locked; - static bool rfkill_epo_lock_active; @@ -392,7 +391,7 @@ void rfkill_epo(void) rfkill_set_block(rfkill, true); for (i = 0; i < NUM_RFKILL_TYPES; i++) { - rfkill_global_states[i].def = rfkill_global_states[i].cur; + rfkill_global_states[i].sav = rfkill_global_states[i].cur; rfkill_global_states[i].cur = true; } @@ -417,7 +416,7 @@ void rfkill_restore_states(void) rfkill_epo_lock_active = false; for (i = 0; i < NUM_RFKILL_TYPES; i++) - __rfkill_switch_all(i, rfkill_global_states[i].def); + __rfkill_switch_all(i, rfkill_global_states[i].sav); mutex_unlock(&rfkill_global_mutex); } @@ -464,29 +463,6 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type) } #endif -void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked) -{ - BUG_ON(type == RFKILL_TYPE_ALL); - - mutex_lock(&rfkill_global_mutex); - - /* don't allow unblock when epo */ - if (rfkill_epo_lock_active && !blocked) - goto out; - - /* too late */ - if (rfkill_states_default_locked & BIT(type)) - goto out; - - rfkill_states_default_locked |= BIT(type); - - rfkill_global_states[type].cur = blocked; - rfkill_global_states[type].def = blocked; - out: - mutex_unlock(&rfkill_global_mutex); -} -EXPORT_SYMBOL(rfkill_set_global_sw_state); - bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) { @@ -532,13 +508,14 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) blocked = blocked || hwblock; spin_unlock_irqrestore(&rfkill->lock, flags); - if (!rfkill->registered) - return blocked; + if (!rfkill->registered) { + rfkill->persistent = true; + } else { + if (prev != blocked && !hwblock) + schedule_work(&rfkill->uevent_work); - if (prev != blocked && !hwblock) - schedule_work(&rfkill->uevent_work); - - rfkill_led_trigger_event(rfkill); + rfkill_led_trigger_event(rfkill); + } return blocked; } @@ -563,13 +540,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) spin_unlock_irqrestore(&rfkill->lock, flags); - if (!rfkill->registered) - return; - - if (swprev != sw || hwprev != hw) - schedule_work(&rfkill->uevent_work); + if (!rfkill->registered) { + rfkill->persistent = true; + } else { + if (swprev != sw || hwprev != hw) + schedule_work(&rfkill->uevent_work); - rfkill_led_trigger_event(rfkill); + rfkill_led_trigger_event(rfkill); + } } EXPORT_SYMBOL(rfkill_set_states); @@ -888,15 +866,6 @@ int __must_check rfkill_register(struct rfkill *rfkill) dev_set_name(dev, "rfkill%lu", rfkill_no); rfkill_no++; - if (!(rfkill_states_default_locked & BIT(rfkill->type))) { - /* first of its kind */ - BUILD_BUG_ON(NUM_RFKILL_TYPES > - sizeof(rfkill_states_default_locked) * 8); - rfkill_states_default_locked |= BIT(rfkill->type); - rfkill_global_states[rfkill->type].cur = - rfkill_global_states[rfkill->type].def; - } - list_add_tail(&rfkill->node, &rfkill_list); error = device_add(dev); @@ -916,7 +885,17 @@ int __must_check rfkill_register(struct rfkill *rfkill) if (rfkill->ops->poll) schedule_delayed_work(&rfkill->poll_work, round_jiffies_relative(POLL_INTERVAL)); - schedule_work(&rfkill->sync_work); + + if (!rfkill->persistent || rfkill_epo_lock_active) { + schedule_work(&rfkill->sync_work); + } else { +#ifdef CONFIG_RFKILL_INPUT + bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW); + + if (!atomic_read(&rfkill_input_disabled)) + __rfkill_switch_all(rfkill->type, soft_blocked); +#endif + } rfkill_send_events(rfkill, RFKILL_OP_ADD); @@ -1193,7 +1172,7 @@ static int __init rfkill_init(void) int i; for (i = 0; i < NUM_RFKILL_TYPES; i++) - rfkill_global_states[i].def = !rfkill_default_state; + rfkill_global_states[i].cur = !rfkill_default_state; error = class_register(&rfkill_class); if (error) -- cgit v1.2.3 From 908209c160da8ecb68052111972b7a21310eac3f Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Mon, 8 Jun 2009 13:12:23 +0100 Subject: rfkill: don't impose global states on resume (just restore the previous states) Once rfkill-input is disabled, the "global" states will only be used as default initial states. Since the states will always be the same after resume, we shouldn't generate events on resume. Signed-off-by: Alan Jenkins Signed-off-by: John W. Linville --- include/linux/rfkill.h | 7 ++++--- net/rfkill/core.c | 6 +----- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index c1dca0b8138b..16e39c7a67fc 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -212,7 +212,7 @@ void rfkill_destroy(struct rfkill *rfkill); * * rfkill drivers that get events when the hard-blocked state changes * use this function to notify the rfkill core (and through that also - * userspace) of the current state -- they should also use this after + * userspace) of the current state. They should also use this after * resume if the state could have changed. * * You need not (but may) call this function if poll_state is assigned. @@ -234,8 +234,9 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); * rfkill drivers that get events when the soft-blocked state changes * (yes, some platforms directly act on input but allow changing again) * use this function to notify the rfkill core (and through that also - * userspace) of the current state -- they should also use this after - * resume if the state could have changed. + * userspace) of the current state. It is not necessary to notify on + * resume; since hibernation can always change the soft-blocked state, + * the rfkill core will unconditionally restore the previous state. * * This function can be called in any context, even from within rfkill * callbacks. diff --git a/net/rfkill/core.c b/net/rfkill/core.c index fa430bd03f14..4e68ab439d5d 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -728,15 +728,11 @@ static int rfkill_resume(struct device *dev) struct rfkill *rfkill = to_rfkill(dev); bool cur; - mutex_lock(&rfkill_global_mutex); - cur = rfkill_global_states[rfkill->type].cur; + cur = !!(rfkill->state & RFKILL_BLOCK_SW); rfkill_set_block(rfkill, cur); - mutex_unlock(&rfkill_global_mutex); rfkill->suspended = false; - schedule_work(&rfkill->uevent_work); - rfkill_resume_polling(rfkill); return 0; -- cgit v1.2.3