LCOV - code coverage report
Current view: top level - drivers/acpi - event.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 7 47 14.9 %
Date: 2022-04-01 13:59:58 Functions: 2 6 33.3 %
Branches: 2 12 16.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * event.c - exporting ACPI events via procfs
       4                 :            :  *
       5                 :            :  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
       6                 :            :  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
       7                 :            :  *
       8                 :            :  */
       9                 :            : 
      10                 :            : #include <linux/spinlock.h>
      11                 :            : #include <linux/export.h>
      12                 :            : #include <linux/proc_fs.h>
      13                 :            : #include <linux/init.h>
      14                 :            : #include <linux/poll.h>
      15                 :            : #include <linux/gfp.h>
      16                 :            : #include <linux/acpi.h>
      17                 :            : #include <net/netlink.h>
      18                 :            : #include <net/genetlink.h>
      19                 :            : 
      20                 :            : #include "internal.h"
      21                 :            : 
      22                 :            : #define _COMPONENT              ACPI_SYSTEM_COMPONENT
      23                 :            : ACPI_MODULE_NAME("event");
      24                 :            : 
      25                 :            : /* ACPI notifier chain */
      26                 :            : static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
      27                 :            : 
      28                 :          0 : int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
      29                 :            : {
      30                 :          0 :         struct acpi_bus_event event;
      31                 :            : 
      32                 :          0 :         strcpy(event.device_class, dev->pnp.device_class);
      33                 :          0 :         strcpy(event.bus_id, dev->pnp.bus_id);
      34                 :          0 :         event.type = type;
      35                 :          0 :         event.data = data;
      36                 :          0 :         return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
      37         [ #  # ]:          0 :                         == NOTIFY_BAD) ? -EINVAL : 0;
      38                 :            : }
      39                 :            : EXPORT_SYMBOL(acpi_notifier_call_chain);
      40                 :            : 
      41                 :          0 : int register_acpi_notifier(struct notifier_block *nb)
      42                 :            : {
      43                 :          0 :         return blocking_notifier_chain_register(&acpi_chain_head, nb);
      44                 :            : }
      45                 :            : EXPORT_SYMBOL(register_acpi_notifier);
      46                 :            : 
      47                 :          0 : int unregister_acpi_notifier(struct notifier_block *nb)
      48                 :            : {
      49                 :          0 :         return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
      50                 :            : }
      51                 :            : EXPORT_SYMBOL(unregister_acpi_notifier);
      52                 :            : 
      53                 :            : #ifdef CONFIG_NET
      54                 :            : static unsigned int acpi_event_seqnum;
      55                 :            : struct acpi_genl_event {
      56                 :            :         acpi_device_class device_class;
      57                 :            :         char bus_id[15];
      58                 :            :         u32 type;
      59                 :            :         u32 data;
      60                 :            : };
      61                 :            : 
      62                 :            : /* attributes of acpi_genl_family */
      63                 :            : enum {
      64                 :            :         ACPI_GENL_ATTR_UNSPEC,
      65                 :            :         ACPI_GENL_ATTR_EVENT,   /* ACPI event info needed by user space */
      66                 :            :         __ACPI_GENL_ATTR_MAX,
      67                 :            : };
      68                 :            : #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
      69                 :            : 
      70                 :            : /* commands supported by the acpi_genl_family */
      71                 :            : enum {
      72                 :            :         ACPI_GENL_CMD_UNSPEC,
      73                 :            :         ACPI_GENL_CMD_EVENT,    /* kernel->user notifications for ACPI events */
      74                 :            :         __ACPI_GENL_CMD_MAX,
      75                 :            : };
      76                 :            : #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
      77                 :            : 
      78                 :            : #define ACPI_GENL_FAMILY_NAME           "acpi_event"
      79                 :            : #define ACPI_GENL_VERSION               0x01
      80                 :            : #define ACPI_GENL_MCAST_GROUP_NAME      "acpi_mc_group"
      81                 :            : 
      82                 :            : static const struct genl_multicast_group acpi_event_mcgrps[] = {
      83                 :            :         { .name = ACPI_GENL_MCAST_GROUP_NAME, },
      84                 :            : };
      85                 :            : 
      86                 :            : static struct genl_family acpi_event_genl_family __ro_after_init = {
      87                 :            :         .module = THIS_MODULE,
      88                 :            :         .name = ACPI_GENL_FAMILY_NAME,
      89                 :            :         .version = ACPI_GENL_VERSION,
      90                 :            :         .maxattr = ACPI_GENL_ATTR_MAX,
      91                 :            :         .mcgrps = acpi_event_mcgrps,
      92                 :            :         .n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
      93                 :            : };
      94                 :            : 
      95                 :          0 : int acpi_bus_generate_netlink_event(const char *device_class,
      96                 :            :                                       const char *bus_id,
      97                 :            :                                       u8 type, int data)
      98                 :            : {
      99                 :          0 :         struct sk_buff *skb;
     100                 :          0 :         struct nlattr *attr;
     101                 :          0 :         struct acpi_genl_event *event;
     102                 :          0 :         void *msg_header;
     103                 :          0 :         int size;
     104                 :            : 
     105                 :            :         /* allocate memory */
     106                 :          0 :         size = nla_total_size(sizeof(struct acpi_genl_event)) +
     107                 :            :             nla_total_size(0);
     108                 :            : 
     109                 :          0 :         skb = genlmsg_new(size, GFP_ATOMIC);
     110         [ #  # ]:          0 :         if (!skb)
     111                 :            :                 return -ENOMEM;
     112                 :            : 
     113                 :            :         /* add the genetlink message header */
     114                 :          0 :         msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
     115                 :            :                                  &acpi_event_genl_family, 0,
     116                 :            :                                  ACPI_GENL_CMD_EVENT);
     117         [ #  # ]:          0 :         if (!msg_header) {
     118                 :          0 :                 nlmsg_free(skb);
     119                 :          0 :                 return -ENOMEM;
     120                 :            :         }
     121                 :            : 
     122                 :            :         /* fill the data */
     123                 :          0 :         attr =
     124                 :          0 :             nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
     125                 :            :                         sizeof(struct acpi_genl_event));
     126         [ #  # ]:          0 :         if (!attr) {
     127                 :          0 :                 nlmsg_free(skb);
     128                 :          0 :                 return -EINVAL;
     129                 :            :         }
     130                 :            : 
     131                 :          0 :         event = nla_data(attr);
     132                 :          0 :         memset(event, 0, sizeof(struct acpi_genl_event));
     133                 :            : 
     134                 :          0 :         strscpy(event->device_class, device_class, sizeof(event->device_class));
     135                 :          0 :         strscpy(event->bus_id, bus_id, sizeof(event->bus_id));
     136                 :          0 :         event->type = type;
     137                 :          0 :         event->data = data;
     138                 :            : 
     139                 :            :         /* send multicast genetlink message */
     140                 :          0 :         genlmsg_end(skb, msg_header);
     141                 :            : 
     142                 :          0 :         genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
     143                 :          0 :         return 0;
     144                 :            : }
     145                 :            : 
     146                 :            : EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
     147                 :            : 
     148                 :         78 : static int __init acpi_event_genetlink_init(void)
     149                 :            : {
     150                 :         78 :         return genl_register_family(&acpi_event_genl_family);
     151                 :            : }
     152                 :            : 
     153                 :            : #else
     154                 :            : int acpi_bus_generate_netlink_event(const char *device_class,
     155                 :            :                                       const char *bus_id,
     156                 :            :                                       u8 type, int data)
     157                 :            : {
     158                 :            :         return 0;
     159                 :            : }
     160                 :            : 
     161                 :            : EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
     162                 :            : 
     163                 :            : static int acpi_event_genetlink_init(void)
     164                 :            : {
     165                 :            :         return -ENODEV;
     166                 :            : }
     167                 :            : #endif
     168                 :            : 
     169                 :         78 : static int __init acpi_event_init(void)
     170                 :            : {
     171                 :         78 :         int error = 0;
     172                 :            : 
     173         [ +  - ]:         78 :         if (acpi_disabled)
     174                 :            :                 return 0;
     175                 :            : 
     176                 :            :         /* create genetlink for acpi event */
     177                 :         78 :         error = acpi_event_genetlink_init();
     178         [ -  + ]:         78 :         if (error)
     179                 :          0 :                 printk(KERN_WARNING PREFIX
     180                 :            :                        "Failed to create genetlink family for ACPI event\n");
     181                 :            :         return 0;
     182                 :            : }
     183                 :            : 
     184                 :            : fs_initcall(acpi_event_init);

Generated by: LCOV version 1.14