root/drivers/char/ipmi/ipmi_si_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipmi_pci_cleanup
  2. ipmi_pci_probe_regspacing
  3. ipmi_pci_probe
  4. ipmi_pci_remove
  5. ipmi_si_pci_init
  6. ipmi_si_pci_shutdown

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * ipmi_si_pci.c
   4  *
   5  * Handling for IPMI devices on the PCI bus.
   6  */
   7 
   8 #define pr_fmt(fmt) "ipmi_pci: " fmt
   9 
  10 #include <linux/module.h>
  11 #include <linux/pci.h>
  12 #include "ipmi_si.h"
  13 
  14 static bool pci_registered;
  15 
  16 static bool si_trypci = true;
  17 
  18 module_param_named(trypci, si_trypci, bool, 0);
  19 MODULE_PARM_DESC(trypci, "Setting this to zero will disable the"
  20                  " default scan of the interfaces identified via pci");
  21 
  22 #define PCI_DEVICE_ID_HP_MMC 0x121A
  23 
  24 static void ipmi_pci_cleanup(struct si_sm_io *io)
  25 {
  26         struct pci_dev *pdev = io->addr_source_data;
  27 
  28         pci_disable_device(pdev);
  29 }
  30 
  31 static int ipmi_pci_probe_regspacing(struct si_sm_io *io)
  32 {
  33         if (io->si_type == SI_KCS) {
  34                 unsigned char   status;
  35                 int             regspacing;
  36 
  37                 io->regsize = DEFAULT_REGSIZE;
  38                 io->regshift = 0;
  39 
  40                 /* detect 1, 4, 16byte spacing */
  41                 for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
  42                         io->regspacing = regspacing;
  43                         if (io->io_setup(io)) {
  44                                 dev_err(io->dev, "Could not setup I/O space\n");
  45                                 return DEFAULT_REGSPACING;
  46                         }
  47                         /* write invalid cmd */
  48                         io->outputb(io, 1, 0x10);
  49                         /* read status back */
  50                         status = io->inputb(io, 1);
  51                         io->io_cleanup(io);
  52                         if (status)
  53                                 return regspacing;
  54                         regspacing *= 4;
  55                 }
  56         }
  57         return DEFAULT_REGSPACING;
  58 }
  59 
  60 static struct pci_device_id ipmi_pci_blacklist[] = {
  61         /*
  62          * This is a "Virtual IPMI device", whatever that is.  It appears
  63          * as a KCS device by the class, but it is not one.
  64          */
  65         { PCI_VDEVICE(REALTEK, 0x816c) },
  66         { 0, }
  67 };
  68 
  69 static int ipmi_pci_probe(struct pci_dev *pdev,
  70                                     const struct pci_device_id *ent)
  71 {
  72         int rv;
  73         struct si_sm_io io;
  74 
  75         if (pci_match_id(ipmi_pci_blacklist, pdev))
  76                 return -ENODEV;
  77 
  78         memset(&io, 0, sizeof(io));
  79         io.addr_source = SI_PCI;
  80         dev_info(&pdev->dev, "probing via PCI");
  81 
  82         switch (pdev->class) {
  83         case PCI_CLASS_SERIAL_IPMI_SMIC:
  84                 io.si_type = SI_SMIC;
  85                 break;
  86 
  87         case PCI_CLASS_SERIAL_IPMI_KCS:
  88                 io.si_type = SI_KCS;
  89                 break;
  90 
  91         case PCI_CLASS_SERIAL_IPMI_BT:
  92                 io.si_type = SI_BT;
  93                 break;
  94 
  95         default:
  96                 dev_info(&pdev->dev, "Unknown IPMI class: %x\n", pdev->class);
  97                 return -ENOMEM;
  98         }
  99 
 100         rv = pci_enable_device(pdev);
 101         if (rv) {
 102                 dev_err(&pdev->dev, "couldn't enable PCI device\n");
 103                 return rv;
 104         }
 105 
 106         io.addr_source_cleanup = ipmi_pci_cleanup;
 107         io.addr_source_data = pdev;
 108 
 109         if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
 110                 io.addr_space = IPMI_IO_ADDR_SPACE;
 111                 io.io_setup = ipmi_si_port_setup;
 112         } else {
 113                 io.addr_space = IPMI_MEM_ADDR_SPACE;
 114                 io.io_setup = ipmi_si_mem_setup;
 115         }
 116         io.addr_data = pci_resource_start(pdev, 0);
 117 
 118         io.dev = &pdev->dev;
 119 
 120         io.regspacing = ipmi_pci_probe_regspacing(&io);
 121         io.regsize = DEFAULT_REGSIZE;
 122         io.regshift = 0;
 123 
 124         io.irq = pdev->irq;
 125         if (io.irq)
 126                 io.irq_setup = ipmi_std_irq_setup;
 127 
 128         dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n",
 129                  &pdev->resource[0], io.regsize, io.regspacing, io.irq);
 130 
 131         rv = ipmi_si_add_smi(&io);
 132         if (rv)
 133                 pci_disable_device(pdev);
 134 
 135         return rv;
 136 }
 137 
 138 static void ipmi_pci_remove(struct pci_dev *pdev)
 139 {
 140         ipmi_si_remove_by_dev(&pdev->dev);
 141 }
 142 
 143 static const struct pci_device_id ipmi_pci_devices[] = {
 144         { PCI_VDEVICE(HP, PCI_DEVICE_ID_HP_MMC) },
 145         { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_SMIC, ~0) },
 146         { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_KCS, ~0) },
 147         { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_BT, ~0) },
 148         { 0, }
 149 };
 150 MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
 151 
 152 static struct pci_driver ipmi_pci_driver = {
 153         .name =         SI_DEVICE_NAME,
 154         .id_table =     ipmi_pci_devices,
 155         .probe =        ipmi_pci_probe,
 156         .remove =       ipmi_pci_remove,
 157 };
 158 
 159 void ipmi_si_pci_init(void)
 160 {
 161         if (si_trypci) {
 162                 int rv = pci_register_driver(&ipmi_pci_driver);
 163                 if (rv)
 164                         pr_err("Unable to register PCI driver: %d\n", rv);
 165                 else
 166                         pci_registered = true;
 167         }
 168 }
 169 
 170 void ipmi_si_pci_shutdown(void)
 171 {
 172         if (pci_registered)
 173                 pci_unregister_driver(&ipmi_pci_driver);
 174 }

/* [<][>][^][v][top][bottom][index][help] */