ACPI: don't duplicate input events on netlink

The previous events patch added a netlink event for every
user of the legacy /proc/acpi/event interface.

However, some users of /proc/acpi/event are really input events,
and they already report their events via the input layer.

Introduce a new interface, acpi_bus_generate_netlink_event(),
which is explicitly called by devices that want to repoprt
events via netlink.  This allows the input-like events
to opt-out of generating netlink events.  In summary:

events that are sent via netlink:
	ac/battery/sbs
	thermal
	processor
	thinkpad_acpi dock/bay

events that are sent via input layer:
	button
	video hotkey
	thinkpad_acpi hotkey
	asus_acpi/asus-laptop hotkey
	sonypi/sonylaptop

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index d8b3509..b53c2cf 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -205,6 +205,9 @@
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_ac_get_state(ac);
 		acpi_bus_generate_event(device, event, (u32) ac->state);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event,
+						  (u32) ac->state);
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index d7b499f..9f0bf90 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -869,6 +869,9 @@
 		acpi_battery_notify_update(battery);
 		acpi_bus_generate_event(device, event,
 					acpi_battery_present(battery));
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event,
+						  acpi_battery_present(battery));
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 6b2658c..e5084ec 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -292,10 +292,6 @@
 	if (!device)
 		return -EINVAL;
 
-	if (acpi_bus_generate_genetlink_event(device, type, data))
-		printk(KERN_WARNING PREFIX
-			"Failed to generate an ACPI event via genetlink!\n");
-
 	/* drop event on the floor if no one's listening */
 	if (!event_is_open)
 		return 0;
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 95637a4..b7b1432 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -147,7 +147,8 @@
 	.name = ACPI_GENL_MCAST_GROUP_NAME,
 };
 
-int acpi_bus_generate_genetlink_event(struct acpi_device *device,
+int acpi_bus_generate_netlink_event(const char *device_class,
+				      const char *bus_id,
 				      u8 type, int data)
 {
 	struct sk_buff *skb;
@@ -191,8 +192,8 @@
 
 	memset(event, 0, sizeof(struct acpi_genl_event));
 
-	strcpy(event->device_class, device->pnp.device_class);
-	strcpy(event->bus_id, device->dev.bus_id);
+	strcpy(event->device_class, device_class);
+	strcpy(event->bus_id, bus_id);
 	event->type = type;
 	event->data = data;
 
@@ -211,6 +212,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
+
 static int acpi_event_genetlink_init(void)
 {
 	int result;
@@ -228,12 +231,14 @@
 }
 
 #else
-int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type,
+int acpi_bus_generate_netlink_event(struct acpi_device *device, u8 type,
 				      int data)
 {
 	return 0;
 }
 
+EXPORT_SYMBOL(acpi_generate_netlink_event);
+
 static int acpi_event_genetlink_init(void)
 {
 	return -ENODEV;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 4984223..dbc2e5d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -700,14 +700,21 @@
 		acpi_processor_ppc_has_changed(pr);
 		acpi_bus_generate_event(device, event,
 					pr->performance_platform_limit);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event,
+						  pr->performance_platform_limit);
 		break;
 	case ACPI_PROCESSOR_NOTIFY_POWER:
 		acpi_processor_cst_has_changed(pr);
 		acpi_bus_generate_event(device, event, 0);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event, 0);
 		break;
 	case ACPI_PROCESSOR_NOTIFY_THROTTLING:
 		acpi_processor_tstate_has_changed(pr);
 		acpi_bus_generate_event(device, event, 0);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event, 0);
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Unsupported event [0x%x]\n", event));
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 82c3a55..2d67e92 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -445,6 +445,7 @@
 	strcpy(acpi_device_bid(device), bid_saved);
 	strcpy(acpi_device_class(device), class_saved);
 
+	acpi_bus_generate_netlink_event(class, bid, event, state);
 	return result;
 }
 
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 1e06159..291758c 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -487,6 +487,10 @@
 	       KELVIN_TO_CELSIUS(tz->temperature));
 	acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
 				tz->trips.critical.flags.enabled);
+	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+					  tz->device->dev.bus_id,
+					  ACPI_THERMAL_NOTIFY_CRITICAL,
+					  tz->trips.critical.flags.enabled);
 
 	orderly_poweroff(true);
 
@@ -506,6 +510,10 @@
 
 	acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
 				tz->trips.hot.flags.enabled);
+	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+					  tz->device->dev.bus_id,
+					  ACPI_THERMAL_NOTIFY_HOT,
+					  tz->trips.hot.flags.enabled);
 
 	/* TBD: Call user-mode "sleep(S4)" function */
 
@@ -1150,11 +1158,15 @@
 		acpi_thermal_get_trip_points(tz);
 		acpi_thermal_check(tz);
 		acpi_bus_generate_event(device, event, 0);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event, 0);
 		break;
 	case ACPI_THERMAL_NOTIFY_DEVICES:
 		if (tz->flags.devices)
 			acpi_thermal_get_devices(tz);
 		acpi_bus_generate_event(device, event, 0);
+		acpi_bus_generate_netlink_event(device->pnp.device_class,
+						  device->dev.bus_id, event, 0);
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index f6cd34a..d0825a3 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -2162,22 +2162,27 @@
 	int docked = dock_docked();
 	int pci = ibm->acpi->hid && ibm->acpi->device &&
 		acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
+	int data;
 
 	if (event == 1 && !pci)	/* 570 */
-		acpi_bus_generate_event(ibm->acpi->device, event, 1);	/* button */
+		data = 1;	/* button */
 	else if (event == 1 && pci)	/* 570 */
-		acpi_bus_generate_event(ibm->acpi->device, event, 3);	/* dock */
+		data = 3;	/* dock */
 	else if (event == 3 && docked)
-		acpi_bus_generate_event(ibm->acpi->device, event, 1);	/* button */
+		data = 1;	/* button */
 	else if (event == 3 && !docked)
-		acpi_bus_generate_event(ibm->acpi->device, event, 2);	/* undock */
+		data = 2;	/* undock */
 	else if (event == 0 && docked)
-		acpi_bus_generate_event(ibm->acpi->device, event, 3);	/* dock */
+		data = 3;	/* dock */
 	else {
 		printk(IBM_ERR "unknown dock event %d, status %d\n",
 		       event, _sta(dock_handle));
-		acpi_bus_generate_event(ibm->acpi->device, event, 0);	/* unknown */
+		data = 0;	/* unknown */
 	}
+	acpi_bus_generate_event(ibm->acpi->device, event, data);
+	acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+					  ibm->acpi->device->dev.bus_id,
+					  event, data);
 }
 
 static int dock_read(char *p)
@@ -2276,6 +2281,9 @@
 static void bay_notify(struct ibm_struct *ibm, u32 event)
 {
 	acpi_bus_generate_event(ibm->acpi->device, event, 0);
+	acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+					  ibm->acpi->device->dev.bus_id,
+					  event, 0);
 }
 
 #define bay_occupied(b) (_sta(b##_handle) & 1)
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 70db38c..3609024 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -268,6 +268,9 @@
 	if (subevent == 0x80) {
 		dbg("%s: generationg bus event\n", __FUNCTION__);
 		acpi_bus_generate_event(note->device, note->event, detail);
+		acpi_bus_generate_netlink_event(note->device->pnp.device_class,
+						  note->device->dev.bus_id,
+						  note->event, detail);
 	} else
 		note->event = event;
 }