LCOV - code coverage report
Current view: top level - drivers/pci/hotplug - pci_hotplug_core.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 73 235 31.1 %
Date: 2022-04-01 13:59:58 Functions: 4 21 19.0 %
Branches: 26 203 12.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0+
       2                 :            : /*
       3                 :            :  * PCI HotPlug Controller Core
       4                 :            :  *
       5                 :            :  * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
       6                 :            :  * Copyright (C) 2001-2002 IBM Corp.
       7                 :            :  *
       8                 :            :  * All rights reserved.
       9                 :            :  *
      10                 :            :  * Send feedback to <kristen.c.accardi@intel.com>
      11                 :            :  *
      12                 :            :  * Authors:
      13                 :            :  *   Greg Kroah-Hartman <greg@kroah.com>
      14                 :            :  *   Scott Murray <scottm@somanetworks.com>
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <linux/module.h> /* try_module_get & module_put */
      18                 :            : #include <linux/moduleparam.h>
      19                 :            : #include <linux/kernel.h>
      20                 :            : #include <linux/types.h>
      21                 :            : #include <linux/list.h>
      22                 :            : #include <linux/kobject.h>
      23                 :            : #include <linux/sysfs.h>
      24                 :            : #include <linux/pagemap.h>
      25                 :            : #include <linux/init.h>
      26                 :            : #include <linux/mount.h>
      27                 :            : #include <linux/namei.h>
      28                 :            : #include <linux/mutex.h>
      29                 :            : #include <linux/pci.h>
      30                 :            : #include <linux/pci_hotplug.h>
      31                 :            : #include <linux/uaccess.h>
      32                 :            : #include "../pci.h"
      33                 :            : #include "cpci_hotplug.h"
      34                 :            : 
      35                 :            : #define MY_NAME "pci_hotplug"
      36                 :            : 
      37                 :            : #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0)
      38                 :            : #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
      39                 :            : #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
      40                 :            : #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
      41                 :            : 
      42                 :            : /* local variables */
      43                 :            : static bool debug;
      44                 :            : 
      45                 :            : static LIST_HEAD(pci_hotplug_slot_list);
      46                 :            : static DEFINE_MUTEX(pci_hp_mutex);
      47                 :            : 
      48                 :            : /* Weee, fun with macros... */
      49                 :            : #define GET_STATUS(name, type)  \
      50                 :            : static int get_##name(struct hotplug_slot *slot, type *value)           \
      51                 :            : {                                                                       \
      52                 :            :         const struct hotplug_slot_ops *ops = slot->ops;                      \
      53                 :            :         int retval = 0;                                                 \
      54                 :            :         if (!try_module_get(slot->owner))                            \
      55                 :            :                 return -ENODEV;                                         \
      56                 :            :         if (ops->get_##name)                                         \
      57                 :            :                 retval = ops->get_##name(slot, value);                       \
      58                 :            :         module_put(slot->owner);                                     \
      59                 :            :         return retval;                                                  \
      60                 :            : }
      61                 :            : 
      62   [ #  #  #  # ]:          0 : GET_STATUS(power_status, u8)
      63   [ #  #  #  # ]:          0 : GET_STATUS(attention_status, u8)
      64   [ #  #  #  # ]:          0 : GET_STATUS(latch_status, u8)
      65   [ #  #  #  # ]:          0 : GET_STATUS(adapter_status, u8)
      66                 :            : 
      67                 :          0 : static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf)
      68                 :            : {
      69                 :          0 :         int retval;
      70                 :          0 :         u8 value;
      71                 :            : 
      72                 :          0 :         retval = get_power_status(pci_slot->hotplug, &value);
      73         [ #  # ]:          0 :         if (retval)
      74                 :          0 :                 return retval;
      75                 :            : 
      76                 :          0 :         return sprintf(buf, "%d\n", value);
      77                 :            : }
      78                 :            : 
      79                 :          0 : static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf,
      80                 :            :                                 size_t count)
      81                 :            : {
      82                 :          0 :         struct hotplug_slot *slot = pci_slot->hotplug;
      83                 :          0 :         unsigned long lpower;
      84                 :          0 :         u8 power;
      85                 :          0 :         int retval = 0;
      86                 :            : 
      87                 :          0 :         lpower = simple_strtoul(buf, NULL, 10);
      88                 :          0 :         power = (u8)(lpower & 0xff);
      89         [ #  # ]:          0 :         dbg("power = %d\n", power);
      90                 :            : 
      91         [ #  # ]:          0 :         if (!try_module_get(slot->owner)) {
      92                 :          0 :                 retval = -ENODEV;
      93                 :          0 :                 goto exit;
      94                 :            :         }
      95      [ #  #  # ]:          0 :         switch (power) {
      96                 :          0 :         case 0:
      97         [ #  # ]:          0 :                 if (slot->ops->disable_slot)
      98                 :          0 :                         retval = slot->ops->disable_slot(slot);
      99                 :            :                 break;
     100                 :            : 
     101                 :          0 :         case 1:
     102         [ #  # ]:          0 :                 if (slot->ops->enable_slot)
     103                 :          0 :                         retval = slot->ops->enable_slot(slot);
     104                 :            :                 break;
     105                 :            : 
     106                 :          0 :         default:
     107                 :          0 :                 err("Illegal value specified for power\n");
     108                 :          0 :                 retval = -EINVAL;
     109                 :            :         }
     110                 :          0 :         module_put(slot->owner);
     111                 :            : 
     112                 :            : exit:
     113         [ #  # ]:          0 :         if (retval)
     114                 :          0 :                 return retval;
     115                 :          0 :         return count;
     116                 :            : }
     117                 :            : 
     118                 :            : static struct pci_slot_attribute hotplug_slot_attr_power = {
     119                 :            :         .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
     120                 :            :         .show = power_read_file,
     121                 :            :         .store = power_write_file
     122                 :            : };
     123                 :            : 
     124                 :          0 : static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf)
     125                 :            : {
     126                 :          0 :         int retval;
     127                 :          0 :         u8 value;
     128                 :            : 
     129                 :          0 :         retval = get_attention_status(pci_slot->hotplug, &value);
     130         [ #  # ]:          0 :         if (retval)
     131                 :          0 :                 return retval;
     132                 :            : 
     133                 :          0 :         return sprintf(buf, "%d\n", value);
     134                 :            : }
     135                 :            : 
     136                 :          0 : static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf,
     137                 :            :                                     size_t count)
     138                 :            : {
     139                 :          0 :         struct hotplug_slot *slot = pci_slot->hotplug;
     140                 :          0 :         const struct hotplug_slot_ops *ops = slot->ops;
     141                 :          0 :         unsigned long lattention;
     142                 :          0 :         u8 attention;
     143                 :          0 :         int retval = 0;
     144                 :            : 
     145                 :          0 :         lattention = simple_strtoul(buf, NULL, 10);
     146                 :          0 :         attention = (u8)(lattention & 0xff);
     147         [ #  # ]:          0 :         dbg(" - attention = %d\n", attention);
     148                 :            : 
     149         [ #  # ]:          0 :         if (!try_module_get(slot->owner)) {
     150                 :          0 :                 retval = -ENODEV;
     151                 :          0 :                 goto exit;
     152                 :            :         }
     153         [ #  # ]:          0 :         if (ops->set_attention_status)
     154                 :          0 :                 retval = ops->set_attention_status(slot, attention);
     155                 :          0 :         module_put(slot->owner);
     156                 :            : 
     157                 :            : exit:
     158         [ #  # ]:          0 :         if (retval)
     159                 :          0 :                 return retval;
     160                 :          0 :         return count;
     161                 :            : }
     162                 :            : 
     163                 :            : static struct pci_slot_attribute hotplug_slot_attr_attention = {
     164                 :            :         .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
     165                 :            :         .show = attention_read_file,
     166                 :            :         .store = attention_write_file
     167                 :            : };
     168                 :            : 
     169                 :          0 : static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf)
     170                 :            : {
     171                 :          0 :         int retval;
     172                 :          0 :         u8 value;
     173                 :            : 
     174                 :          0 :         retval = get_latch_status(pci_slot->hotplug, &value);
     175         [ #  # ]:          0 :         if (retval)
     176                 :          0 :                 return retval;
     177                 :            : 
     178                 :          0 :         return sprintf(buf, "%d\n", value);
     179                 :            : }
     180                 :            : 
     181                 :            : static struct pci_slot_attribute hotplug_slot_attr_latch = {
     182                 :            :         .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO},
     183                 :            :         .show = latch_read_file,
     184                 :            : };
     185                 :            : 
     186                 :          0 : static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf)
     187                 :            : {
     188                 :          0 :         int retval;
     189                 :          0 :         u8 value;
     190                 :            : 
     191                 :          0 :         retval = get_adapter_status(pci_slot->hotplug, &value);
     192         [ #  # ]:          0 :         if (retval)
     193                 :          0 :                 return retval;
     194                 :            : 
     195                 :          0 :         return sprintf(buf, "%d\n", value);
     196                 :            : }
     197                 :            : 
     198                 :            : static struct pci_slot_attribute hotplug_slot_attr_presence = {
     199                 :            :         .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO},
     200                 :            :         .show = presence_read_file,
     201                 :            : };
     202                 :            : 
     203                 :          0 : static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
     204                 :            :                                size_t count)
     205                 :            : {
     206                 :          0 :         struct hotplug_slot *slot = pci_slot->hotplug;
     207                 :          0 :         unsigned long ltest;
     208                 :          0 :         u32 test;
     209                 :          0 :         int retval = 0;
     210                 :            : 
     211                 :          0 :         ltest = simple_strtoul(buf, NULL, 10);
     212                 :          0 :         test = (u32)(ltest & 0xffffffff);
     213         [ #  # ]:          0 :         dbg("test = %d\n", test);
     214                 :            : 
     215         [ #  # ]:          0 :         if (!try_module_get(slot->owner)) {
     216                 :          0 :                 retval = -ENODEV;
     217                 :          0 :                 goto exit;
     218                 :            :         }
     219         [ #  # ]:          0 :         if (slot->ops->hardware_test)
     220                 :          0 :                 retval = slot->ops->hardware_test(slot, test);
     221                 :          0 :         module_put(slot->owner);
     222                 :            : 
     223                 :            : exit:
     224         [ #  # ]:          0 :         if (retval)
     225                 :          0 :                 return retval;
     226                 :          0 :         return count;
     227                 :            : }
     228                 :            : 
     229                 :            : static struct pci_slot_attribute hotplug_slot_attr_test = {
     230                 :            :         .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
     231                 :            :         .store = test_write_file
     232                 :            : };
     233                 :            : 
     234                 :       2262 : static bool has_power_file(struct pci_slot *pci_slot)
     235                 :            : {
     236                 :       2262 :         struct hotplug_slot *slot = pci_slot->hotplug;
     237                 :            : 
     238   [ -  -  +  -  :       2262 :         if ((!slot) || (!slot->ops))
                   -  - ]
     239                 :            :                 return false;
     240   [ -  -  -  +  :       2262 :         if ((slot->ops->enable_slot) ||
                   -  - ]
     241   [ #  #  #  #  :          0 :             (slot->ops->disable_slot) ||
                   #  # ]
     242   [ #  #  #  #  :          0 :             (slot->ops->get_power_status))
                   #  # ]
     243                 :       2262 :                 return true;
     244                 :            :         return false;
     245                 :            : }
     246                 :            : 
     247                 :       2262 : static bool has_attention_file(struct pci_slot *pci_slot)
     248                 :            : {
     249                 :       2262 :         struct hotplug_slot *slot = pci_slot->hotplug;
     250                 :            : 
     251   [ -  -  +  -  :       2262 :         if ((!slot) || (!slot->ops))
                   -  - ]
     252                 :            :                 return false;
     253   [ -  -  -  +  :       2262 :         if ((slot->ops->set_attention_status) ||
                   -  - ]
     254   [ #  #  #  #  :          0 :             (slot->ops->get_attention_status))
                   #  # ]
     255                 :       2262 :                 return true;
     256                 :            :         return false;
     257                 :            : }
     258                 :            : 
     259                 :       2262 : static bool has_latch_file(struct pci_slot *pci_slot)
     260                 :            : {
     261                 :       2262 :         struct hotplug_slot *slot = pci_slot->hotplug;
     262                 :            : 
     263   [ -  -  +  -  :       2262 :         if ((!slot) || (!slot->ops))
                   -  - ]
     264                 :            :                 return false;
     265   [ -  -  +  -  :       2262 :         if (slot->ops->get_latch_status)
                   -  - ]
     266                 :       2262 :                 return true;
     267                 :            :         return false;
     268                 :            : }
     269                 :            : 
     270                 :       2262 : static bool has_adapter_file(struct pci_slot *pci_slot)
     271                 :            : {
     272                 :       2262 :         struct hotplug_slot *slot = pci_slot->hotplug;
     273                 :            : 
     274   [ -  -  +  -  :       2262 :         if ((!slot) || (!slot->ops))
                   -  - ]
     275                 :            :                 return false;
     276   [ -  -  +  -  :       2262 :         if (slot->ops->get_adapter_status)
                   -  - ]
     277                 :       2262 :                 return true;
     278                 :            :         return false;
     279                 :            : }
     280                 :            : 
     281                 :       2262 : static bool has_test_file(struct pci_slot *pci_slot)
     282                 :            : {
     283                 :       2262 :         struct hotplug_slot *slot = pci_slot->hotplug;
     284                 :            : 
     285   [ -  -  +  - ]:       2262 :         if ((!slot) || (!slot->ops))
     286                 :            :                 return false;
     287   [ -  -  -  + ]:       2262 :         if (slot->ops->hardware_test)
     288                 :          0 :                 return true;
     289                 :            :         return false;
     290                 :            : }
     291                 :            : 
     292                 :       2262 : static int fs_add_slot(struct pci_slot *pci_slot)
     293                 :            : {
     294                 :       2262 :         int retval = 0;
     295                 :            : 
     296                 :            :         /* Create symbolic link to the hotplug driver module */
     297                 :       2262 :         pci_hp_create_module_link(pci_slot);
     298                 :            : 
     299         [ +  - ]:       2262 :         if (has_power_file(pci_slot)) {
     300                 :       2262 :                 retval = sysfs_create_file(&pci_slot->kobj,
     301                 :            :                                            &hotplug_slot_attr_power.attr);
     302         [ -  + ]:       2262 :                 if (retval)
     303                 :          0 :                         goto exit_power;
     304                 :            :         }
     305                 :            : 
     306         [ +  - ]:       2262 :         if (has_attention_file(pci_slot)) {
     307                 :       2262 :                 retval = sysfs_create_file(&pci_slot->kobj,
     308                 :            :                                            &hotplug_slot_attr_attention.attr);
     309         [ -  + ]:       2262 :                 if (retval)
     310                 :          0 :                         goto exit_attention;
     311                 :            :         }
     312                 :            : 
     313         [ +  - ]:       2262 :         if (has_latch_file(pci_slot)) {
     314                 :       2262 :                 retval = sysfs_create_file(&pci_slot->kobj,
     315                 :            :                                            &hotplug_slot_attr_latch.attr);
     316         [ -  + ]:       2262 :                 if (retval)
     317                 :          0 :                         goto exit_latch;
     318                 :            :         }
     319                 :            : 
     320         [ +  - ]:       2262 :         if (has_adapter_file(pci_slot)) {
     321                 :       2262 :                 retval = sysfs_create_file(&pci_slot->kobj,
     322                 :            :                                            &hotplug_slot_attr_presence.attr);
     323         [ -  + ]:       2262 :                 if (retval)
     324                 :          0 :                         goto exit_adapter;
     325                 :            :         }
     326                 :            : 
     327         [ +  - ]:       2262 :         if (has_test_file(pci_slot)) {
     328                 :          0 :                 retval = sysfs_create_file(&pci_slot->kobj,
     329                 :            :                                            &hotplug_slot_attr_test.attr);
     330         [ #  # ]:          0 :                 if (retval)
     331                 :          0 :                         goto exit_test;
     332                 :            :         }
     333                 :            : 
     334                 :       2262 :         goto exit;
     335                 :            : 
     336                 :            : exit_test:
     337         [ #  # ]:          0 :         if (has_adapter_file(pci_slot))
     338                 :          0 :                 sysfs_remove_file(&pci_slot->kobj,
     339                 :            :                                   &hotplug_slot_attr_presence.attr);
     340                 :          0 : exit_adapter:
     341         [ #  # ]:          0 :         if (has_latch_file(pci_slot))
     342                 :          0 :                 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
     343                 :          0 : exit_latch:
     344         [ #  # ]:          0 :         if (has_attention_file(pci_slot))
     345                 :          0 :                 sysfs_remove_file(&pci_slot->kobj,
     346                 :            :                                   &hotplug_slot_attr_attention.attr);
     347                 :          0 : exit_attention:
     348         [ #  # ]:          0 :         if (has_power_file(pci_slot))
     349                 :          0 :                 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
     350                 :          0 : exit_power:
     351                 :          0 :         pci_hp_remove_module_link(pci_slot);
     352                 :       2262 : exit:
     353                 :       2262 :         return retval;
     354                 :            : }
     355                 :            : 
     356                 :          0 : static void fs_remove_slot(struct pci_slot *pci_slot)
     357                 :            : {
     358         [ #  # ]:          0 :         if (has_power_file(pci_slot))
     359                 :          0 :                 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
     360                 :            : 
     361         [ #  # ]:          0 :         if (has_attention_file(pci_slot))
     362                 :          0 :                 sysfs_remove_file(&pci_slot->kobj,
     363                 :            :                                   &hotplug_slot_attr_attention.attr);
     364                 :            : 
     365         [ #  # ]:          0 :         if (has_latch_file(pci_slot))
     366                 :          0 :                 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
     367                 :            : 
     368         [ #  # ]:          0 :         if (has_adapter_file(pci_slot))
     369                 :          0 :                 sysfs_remove_file(&pci_slot->kobj,
     370                 :            :                                   &hotplug_slot_attr_presence.attr);
     371                 :            : 
     372         [ #  # ]:          0 :         if (has_test_file(pci_slot))
     373                 :          0 :                 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr);
     374                 :            : 
     375                 :          0 :         pci_hp_remove_module_link(pci_slot);
     376                 :          0 : }
     377                 :            : 
     378                 :          0 : static struct hotplug_slot *get_slot_from_name(const char *name)
     379                 :            : {
     380                 :          0 :         struct hotplug_slot *slot;
     381                 :            : 
     382         [ #  # ]:          0 :         list_for_each_entry(slot, &pci_hotplug_slot_list, slot_list) {
     383         [ #  # ]:          0 :                 if (strcmp(hotplug_slot_name(slot), name) == 0)
     384                 :          0 :                         return slot;
     385                 :            :         }
     386                 :            :         return NULL;
     387                 :            : }
     388                 :            : 
     389                 :            : /**
     390                 :            :  * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
     391                 :            :  * @bus: bus this slot is on
     392                 :            :  * @slot: pointer to the &struct hotplug_slot to register
     393                 :            :  * @devnr: device number
     394                 :            :  * @name: name registered with kobject core
     395                 :            :  * @owner: caller module owner
     396                 :            :  * @mod_name: caller module name
     397                 :            :  *
     398                 :            :  * Prepares a hotplug slot for in-kernel use and immediately publishes it to
     399                 :            :  * user space in one go.  Drivers may alternatively carry out the two steps
     400                 :            :  * separately by invoking pci_hp_initialize() and pci_hp_add().
     401                 :            :  *
     402                 :            :  * Returns 0 if successful, anything else for an error.
     403                 :            :  */
     404                 :       2262 : int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
     405                 :            :                       int devnr, const char *name,
     406                 :            :                       struct module *owner, const char *mod_name)
     407                 :            : {
     408                 :       2262 :         int result;
     409                 :            : 
     410                 :       2262 :         result = __pci_hp_initialize(slot, bus, devnr, name, owner, mod_name);
     411         [ #  # ]:          0 :         if (result)
     412                 :          0 :                 return result;
     413                 :            : 
     414                 :       2262 :         result = pci_hp_add(slot);
     415         [ -  + ]:       2262 :         if (result)
     416                 :          0 :                 pci_hp_destroy(slot);
     417                 :            : 
     418                 :            :         return result;
     419                 :            : }
     420                 :            : EXPORT_SYMBOL_GPL(__pci_hp_register);
     421                 :            : 
     422                 :            : /**
     423                 :            :  * __pci_hp_initialize - prepare hotplug slot for in-kernel use
     424                 :            :  * @slot: pointer to the &struct hotplug_slot to initialize
     425                 :            :  * @bus: bus this slot is on
     426                 :            :  * @devnr: slot number
     427                 :            :  * @name: name registered with kobject core
     428                 :            :  * @owner: caller module owner
     429                 :            :  * @mod_name: caller module name
     430                 :            :  *
     431                 :            :  * Allocate and fill in a PCI slot for use by a hotplug driver.  Once this has
     432                 :            :  * been called, the driver may invoke hotplug_slot_name() to get the slot's
     433                 :            :  * unique name.  The driver must be prepared to handle a ->reset_slot callback
     434                 :            :  * from this point on.
     435                 :            :  *
     436                 :            :  * Returns 0 on success or a negative int on error.
     437                 :            :  */
     438                 :       2262 : int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus,
     439                 :            :                         int devnr, const char *name, struct module *owner,
     440                 :            :                         const char *mod_name)
     441                 :            : {
     442                 :       2262 :         struct pci_slot *pci_slot;
     443                 :            : 
     444   [ -  -  +  - ]:       2262 :         if (slot == NULL)
     445                 :            :                 return -ENODEV;
     446   [ -  -  +  - ]:       2262 :         if (slot->ops == NULL)
     447                 :            :                 return -EINVAL;
     448                 :            : 
     449                 :       2262 :         slot->owner = owner;
     450                 :       2262 :         slot->mod_name = mod_name;
     451                 :            : 
     452                 :            :         /*
     453                 :            :          * No problems if we call this interface from both ACPI_PCI_SLOT
     454                 :            :          * driver and call it here again. If we've already created the
     455                 :            :          * pci_slot, the interface will simply bump the refcount.
     456                 :            :          */
     457                 :       2262 :         pci_slot = pci_create_slot(bus, devnr, name, slot);
     458   [ -  -  -  + ]:       2262 :         if (IS_ERR(pci_slot))
     459         [ #  # ]:          0 :                 return PTR_ERR(pci_slot);
     460                 :            : 
     461                 :       2262 :         slot->pci_slot = pci_slot;
     462                 :       2262 :         pci_slot->hotplug = slot;
     463                 :       2262 :         return 0;
     464                 :            : }
     465                 :            : EXPORT_SYMBOL_GPL(__pci_hp_initialize);
     466                 :            : 
     467                 :            : /**
     468                 :            :  * pci_hp_add - publish hotplug slot to user space
     469                 :            :  * @slot: pointer to the &struct hotplug_slot to publish
     470                 :            :  *
     471                 :            :  * Make a hotplug slot's sysfs interface available and inform user space of its
     472                 :            :  * addition by sending a uevent.  The hotplug driver must be prepared to handle
     473                 :            :  * all &struct hotplug_slot_ops callbacks from this point on.
     474                 :            :  *
     475                 :            :  * Returns 0 on success or a negative int on error.
     476                 :            :  */
     477                 :       2262 : int pci_hp_add(struct hotplug_slot *slot)
     478                 :            : {
     479                 :       2262 :         struct pci_slot *pci_slot = slot->pci_slot;
     480                 :       2262 :         int result;
     481                 :            : 
     482                 :       2262 :         result = fs_add_slot(pci_slot);
     483         [ +  - ]:       2262 :         if (result)
     484                 :            :                 return result;
     485                 :            : 
     486                 :       2262 :         kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
     487                 :       2262 :         mutex_lock(&pci_hp_mutex);
     488                 :       2262 :         list_add(&slot->slot_list, &pci_hotplug_slot_list);
     489                 :       2262 :         mutex_unlock(&pci_hp_mutex);
     490         [ -  + ]:       2262 :         dbg("Added slot %s to the list\n", hotplug_slot_name(slot));
     491                 :            :         return 0;
     492                 :            : }
     493                 :            : EXPORT_SYMBOL_GPL(pci_hp_add);
     494                 :            : 
     495                 :            : /**
     496                 :            :  * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
     497                 :            :  * @slot: pointer to the &struct hotplug_slot to deregister
     498                 :            :  *
     499                 :            :  * The @slot must have been registered with the pci hotplug subsystem
     500                 :            :  * previously with a call to pci_hp_register().
     501                 :            :  *
     502                 :            :  * Returns 0 if successful, anything else for an error.
     503                 :            :  */
     504                 :          0 : void pci_hp_deregister(struct hotplug_slot *slot)
     505                 :            : {
     506                 :          0 :         pci_hp_del(slot);
     507                 :          0 :         pci_hp_destroy(slot);
     508                 :          0 : }
     509                 :            : EXPORT_SYMBOL_GPL(pci_hp_deregister);
     510                 :            : 
     511                 :            : /**
     512                 :            :  * pci_hp_del - unpublish hotplug slot from user space
     513                 :            :  * @slot: pointer to the &struct hotplug_slot to unpublish
     514                 :            :  *
     515                 :            :  * Remove a hotplug slot's sysfs interface.
     516                 :            :  *
     517                 :            :  * Returns 0 on success or a negative int on error.
     518                 :            :  */
     519                 :          0 : void pci_hp_del(struct hotplug_slot *slot)
     520                 :            : {
     521                 :          0 :         struct hotplug_slot *temp;
     522                 :            : 
     523   [ #  #  #  # ]:          0 :         if (WARN_ON(!slot))
     524                 :            :                 return;
     525                 :            : 
     526                 :          0 :         mutex_lock(&pci_hp_mutex);
     527                 :          0 :         temp = get_slot_from_name(hotplug_slot_name(slot));
     528   [ #  #  #  # ]:          0 :         if (WARN_ON(temp != slot)) {
     529                 :          0 :                 mutex_unlock(&pci_hp_mutex);
     530                 :          0 :                 return;
     531                 :            :         }
     532                 :            : 
     533                 :          0 :         list_del(&slot->slot_list);
     534                 :          0 :         mutex_unlock(&pci_hp_mutex);
     535         [ #  # ]:          0 :         dbg("Removed slot %s from the list\n", hotplug_slot_name(slot));
     536                 :          0 :         fs_remove_slot(slot->pci_slot);
     537                 :            : }
     538                 :            : EXPORT_SYMBOL_GPL(pci_hp_del);
     539                 :            : 
     540                 :            : /**
     541                 :            :  * pci_hp_destroy - remove hotplug slot from in-kernel use
     542                 :            :  * @slot: pointer to the &struct hotplug_slot to destroy
     543                 :            :  *
     544                 :            :  * Destroy a PCI slot used by a hotplug driver.  Once this has been called,
     545                 :            :  * the driver may no longer invoke hotplug_slot_name() to get the slot's
     546                 :            :  * unique name.  The driver no longer needs to handle a ->reset_slot callback
     547                 :            :  * from this point on.
     548                 :            :  *
     549                 :            :  * Returns 0 on success or a negative int on error.
     550                 :            :  */
     551                 :          0 : void pci_hp_destroy(struct hotplug_slot *slot)
     552                 :            : {
     553                 :          0 :         struct pci_slot *pci_slot = slot->pci_slot;
     554                 :            : 
     555                 :          0 :         slot->pci_slot = NULL;
     556                 :          0 :         pci_slot->hotplug = NULL;
     557                 :          0 :         pci_destroy_slot(pci_slot);
     558                 :          0 : }
     559                 :            : EXPORT_SYMBOL_GPL(pci_hp_destroy);
     560                 :            : 
     561                 :         78 : static int __init pci_hotplug_init(void)
     562                 :            : {
     563                 :         78 :         int result;
     564                 :            : 
     565                 :         78 :         result = cpci_hotplug_init(debug);
     566         [ -  + ]:         78 :         if (result) {
     567                 :          0 :                 err("cpci_hotplug_init with error %d\n", result);
     568                 :          0 :                 return result;
     569                 :            :         }
     570                 :            : 
     571                 :            :         return result;
     572                 :            : }
     573                 :            : device_initcall(pci_hotplug_init);
     574                 :            : 
     575                 :            : /*
     576                 :            :  * not really modular, but the easiest way to keep compat with existing
     577                 :            :  * bootargs behaviour is to continue using module_param here.
     578                 :            :  */
     579                 :            : module_param(debug, bool, 0644);
     580                 :            : MODULE_PARM_DESC(debug, "Debugging mode enabled or not");

Generated by: LCOV version 1.14