Skip to content

Commit b05ffc9

Browse files
palidvhart
authored andcommitted
dell-rbtn: Export notifier for other kernel modules
This patch exports notifier functions so other modules can receive HW switch events. By default when some module register notifier, dell-rbtn driver automatically remove rfkill interfaces from system (it is expected that other module will use events for other rfkill interface). This behaviour can be changed with new module parameter "auto_remove_rfkill". This patch is designed for dell-laptop module for receiving those events. Signed-off-by: Pali Rohár <[email protected]> Tested-by: Gabriele Mazzotta <[email protected]> [[email protected]: Cleanup MODULE_PARM_DESC formatting and grammar] Signed-off-by: Darren Hart <[email protected]>
1 parent 817a5cd commit b05ffc9

File tree

2 files changed

+116
-1
lines changed

2 files changed

+116
-1
lines changed

drivers/platform/x86/dell-rbtn.c

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,86 @@ static struct acpi_driver rbtn_driver = {
232232
};
233233

234234

235+
/*
236+
* notifier export functions
237+
*/
238+
239+
static bool auto_remove_rfkill = true;
240+
241+
static ATOMIC_NOTIFIER_HEAD(rbtn_chain_head);
242+
243+
static int rbtn_inc_count(struct device *dev, void *data)
244+
{
245+
struct acpi_device *device = to_acpi_device(dev);
246+
struct rbtn_data *rbtn_data = device->driver_data;
247+
int *count = data;
248+
249+
if (rbtn_data->type == RBTN_SLIDER)
250+
(*count)++;
251+
252+
return 0;
253+
}
254+
255+
static int rbtn_switch_dev(struct device *dev, void *data)
256+
{
257+
struct acpi_device *device = to_acpi_device(dev);
258+
struct rbtn_data *rbtn_data = device->driver_data;
259+
bool enable = data;
260+
261+
if (rbtn_data->type != RBTN_SLIDER)
262+
return 0;
263+
264+
if (enable)
265+
rbtn_rfkill_init(device);
266+
else
267+
rbtn_rfkill_exit(device);
268+
269+
return 0;
270+
}
271+
272+
int dell_rbtn_notifier_register(struct notifier_block *nb)
273+
{
274+
bool first;
275+
int count;
276+
int ret;
277+
278+
count = 0;
279+
ret = driver_for_each_device(&rbtn_driver.drv, NULL, &count,
280+
rbtn_inc_count);
281+
if (ret || count == 0)
282+
return -ENODEV;
283+
284+
first = !rbtn_chain_head.head;
285+
286+
ret = atomic_notifier_chain_register(&rbtn_chain_head, nb);
287+
if (ret != 0)
288+
return ret;
289+
290+
if (auto_remove_rfkill && first)
291+
ret = driver_for_each_device(&rbtn_driver.drv, NULL,
292+
(void *)false, rbtn_switch_dev);
293+
294+
return ret;
295+
}
296+
EXPORT_SYMBOL_GPL(dell_rbtn_notifier_register);
297+
298+
int dell_rbtn_notifier_unregister(struct notifier_block *nb)
299+
{
300+
int ret;
301+
302+
ret = atomic_notifier_chain_unregister(&rbtn_chain_head, nb);
303+
if (ret != 0)
304+
return ret;
305+
306+
if (auto_remove_rfkill && !rbtn_chain_head.head)
307+
ret = driver_for_each_device(&rbtn_driver.drv, NULL,
308+
(void *)true, rbtn_switch_dev);
309+
310+
return ret;
311+
}
312+
EXPORT_SYMBOL_GPL(dell_rbtn_notifier_unregister);
313+
314+
235315
/*
236316
* acpi driver functions
237317
*/
@@ -266,7 +346,10 @@ static int rbtn_add(struct acpi_device *device)
266346
ret = rbtn_input_init(rbtn_data);
267347
break;
268348
case RBTN_SLIDER:
269-
ret = rbtn_rfkill_init(device);
349+
if (auto_remove_rfkill && rbtn_chain_head.head)
350+
ret = 0;
351+
else
352+
ret = rbtn_rfkill_init(device);
270353
break;
271354
default:
272355
ret = -EINVAL;
@@ -313,6 +396,7 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
313396
break;
314397
case RBTN_SLIDER:
315398
rbtn_rfkill_event(device);
399+
atomic_notifier_call_chain(&rbtn_chain_head, event, device);
316400
break;
317401
default:
318402
break;
@@ -326,6 +410,13 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
326410

327411
module_acpi_driver(rbtn_driver);
328412

413+
module_param(auto_remove_rfkill, bool, 0444);
414+
415+
MODULE_PARM_DESC(auto_remove_rfkill, "Automatically remove rfkill devices when "
416+
"other modules start receiving events "
417+
"from this module and re-add them when "
418+
"the last module stops receiving events "
419+
"(default true)");
329420
MODULE_DEVICE_TABLE(acpi, rbtn_ids);
330421
MODULE_DESCRIPTION("Dell Airplane Mode Switch driver");
331422
MODULE_AUTHOR("Pali Rohár <[email protected]>");

drivers/platform/x86/dell-rbtn.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
Dell Airplane Mode Switch driver
3+
Copyright (C) 2014-2015 Pali Rohár <[email protected]>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 2 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
*/
15+
16+
#ifndef _DELL_RBTN_H_
17+
#define _DELL_RBTN_H_
18+
19+
struct notifier_block;
20+
21+
int dell_rbtn_notifier_register(struct notifier_block *nb);
22+
int dell_rbtn_notifier_unregister(struct notifier_block *nb);
23+
24+
#endif

0 commit comments

Comments
 (0)