aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/rfkill/rfkill.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 3edc585dcfa6..4ae4486c77ea 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -62,19 +62,39 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
62#endif /* CONFIG_RFKILL_LEDS */ 62#endif /* CONFIG_RFKILL_LEDS */
63} 63}
64 64
65static void update_rfkill_state(struct rfkill *rfkill)
66{
67 enum rfkill_state newstate;
68
69 if (rfkill->get_state) {
70 mutex_lock(&rfkill->mutex);
71 if (!rfkill->get_state(rfkill->data, &newstate))
72 rfkill->state = newstate;
73 mutex_unlock(&rfkill->mutex);
74 }
75}
76
65static int rfkill_toggle_radio(struct rfkill *rfkill, 77static int rfkill_toggle_radio(struct rfkill *rfkill,
66 enum rfkill_state state) 78 enum rfkill_state state)
67{ 79{
68 int retval = 0; 80 int retval = 0;
81 enum rfkill_state oldstate, newstate;
82
83 oldstate = rfkill->state;
84
85 if (rfkill->get_state &&
86 !rfkill->get_state(rfkill->data, &newstate))
87 rfkill->state = newstate;
69 88
70 if (state != rfkill->state) { 89 if (state != rfkill->state) {
71 retval = rfkill->toggle_radio(rfkill->data, state); 90 retval = rfkill->toggle_radio(rfkill->data, state);
72 if (!retval) { 91 if (!retval)
73 rfkill->state = state; 92 rfkill->state = state;
74 rfkill_led_trigger(rfkill, state);
75 }
76 } 93 }
77 94
95 if (rfkill->state != oldstate)
96 rfkill_led_trigger(rfkill, rfkill->state);
97
78 return retval; 98 return retval;
79} 99}
80 100
@@ -105,6 +125,32 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
105} 125}
106EXPORT_SYMBOL(rfkill_switch_all); 126EXPORT_SYMBOL(rfkill_switch_all);
107 127
128/**
129 * rfkill_force_state - Force the internal rfkill radio state
130 * @rfkill: pointer to the rfkill class to modify.
131 * @state: the current radio state the class should be forced to.
132 *
133 * This function updates the internal state of the radio cached
134 * by the rfkill class. It should be used when the driver gets
135 * a notification by the firmware/hardware of the current *real*
136 * state of the radio rfkill switch.
137 *
138 * It may not be called from an atomic context.
139 */
140int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
141{
142 if (state != RFKILL_STATE_OFF &&
143 state != RFKILL_STATE_ON)
144 return -EINVAL;
145
146 mutex_lock(&rfkill->mutex);
147 rfkill->state = state;
148 mutex_unlock(&rfkill->mutex);
149
150 return 0;
151}
152EXPORT_SYMBOL(rfkill_force_state);
153
108static ssize_t rfkill_name_show(struct device *dev, 154static ssize_t rfkill_name_show(struct device *dev,
109 struct device_attribute *attr, 155 struct device_attribute *attr,
110 char *buf) 156 char *buf)
@@ -147,6 +193,7 @@ static ssize_t rfkill_state_show(struct device *dev,
147{ 193{
148 struct rfkill *rfkill = to_rfkill(dev); 194 struct rfkill *rfkill = to_rfkill(dev);
149 195
196 update_rfkill_state(rfkill);
150 return sprintf(buf, "%d\n", rfkill->state); 197 return sprintf(buf, "%d\n", rfkill->state);
151} 198}
152 199