root/drivers/pci/hotplug/cpci_hotplug_pci.c

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

DEFINITIONS

This source file includes following definitions.
  1. cpci_get_attention_status
  2. cpci_set_attention_status
  3. cpci_get_hs_csr
  4. cpci_check_and_clear_ins
  5. cpci_check_ext
  6. cpci_clear_ext
  7. cpci_led_on
  8. cpci_led_off
  9. cpci_configure_slot
  10. cpci_unconfigure_slot

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * CompactPCI Hot Plug Driver PCI functions
   4  *
   5  * Copyright (C) 2002,2005 by SOMA Networks, Inc.
   6  *
   7  * All rights reserved.
   8  *
   9  * Send feedback to <scottm@somanetworks.com>
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/kernel.h>
  14 #include <linux/pci.h>
  15 #include <linux/pci_hotplug.h>
  16 #include <linux/proc_fs.h>
  17 #include "../pci.h"
  18 #include "cpci_hotplug.h"
  19 
  20 #define MY_NAME "cpci_hotplug"
  21 
  22 extern int cpci_debug;
  23 
  24 #define dbg(format, arg...)                                     \
  25         do {                                                    \
  26                 if (cpci_debug)                                 \
  27                         printk(KERN_DEBUG "%s: " format "\n",   \
  28                                 MY_NAME, ## arg);               \
  29         } while (0)
  30 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
  31 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
  32 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
  33 
  34 
  35 u8 cpci_get_attention_status(struct slot *slot)
  36 {
  37         int hs_cap;
  38         u16 hs_csr;
  39 
  40         hs_cap = pci_bus_find_capability(slot->bus,
  41                                          slot->devfn,
  42                                          PCI_CAP_ID_CHSWP);
  43         if (!hs_cap)
  44                 return 0;
  45 
  46         if (pci_bus_read_config_word(slot->bus,
  47                                      slot->devfn,
  48                                      hs_cap + 2,
  49                                      &hs_csr))
  50                 return 0;
  51 
  52         return hs_csr & 0x0008 ? 1 : 0;
  53 }
  54 
  55 int cpci_set_attention_status(struct slot *slot, int status)
  56 {
  57         int hs_cap;
  58         u16 hs_csr;
  59 
  60         hs_cap = pci_bus_find_capability(slot->bus,
  61                                          slot->devfn,
  62                                          PCI_CAP_ID_CHSWP);
  63         if (!hs_cap)
  64                 return 0;
  65         if (pci_bus_read_config_word(slot->bus,
  66                                      slot->devfn,
  67                                      hs_cap + 2,
  68                                      &hs_csr))
  69                 return 0;
  70         if (status)
  71                 hs_csr |= HS_CSR_LOO;
  72         else
  73                 hs_csr &= ~HS_CSR_LOO;
  74         if (pci_bus_write_config_word(slot->bus,
  75                                       slot->devfn,
  76                                       hs_cap + 2,
  77                                       hs_csr))
  78                 return 0;
  79         return 1;
  80 }
  81 
  82 u16 cpci_get_hs_csr(struct slot *slot)
  83 {
  84         int hs_cap;
  85         u16 hs_csr;
  86 
  87         hs_cap = pci_bus_find_capability(slot->bus,
  88                                          slot->devfn,
  89                                          PCI_CAP_ID_CHSWP);
  90         if (!hs_cap)
  91                 return 0xFFFF;
  92         if (pci_bus_read_config_word(slot->bus,
  93                                      slot->devfn,
  94                                      hs_cap + 2,
  95                                      &hs_csr))
  96                 return 0xFFFF;
  97         return hs_csr;
  98 }
  99 
 100 int cpci_check_and_clear_ins(struct slot *slot)
 101 {
 102         int hs_cap;
 103         u16 hs_csr;
 104         int ins = 0;
 105 
 106         hs_cap = pci_bus_find_capability(slot->bus,
 107                                          slot->devfn,
 108                                          PCI_CAP_ID_CHSWP);
 109         if (!hs_cap)
 110                 return 0;
 111         if (pci_bus_read_config_word(slot->bus,
 112                                      slot->devfn,
 113                                      hs_cap + 2,
 114                                      &hs_csr))
 115                 return 0;
 116         if (hs_csr & HS_CSR_INS) {
 117                 /* Clear INS (by setting it) */
 118                 if (pci_bus_write_config_word(slot->bus,
 119                                               slot->devfn,
 120                                               hs_cap + 2,
 121                                               hs_csr))
 122                         ins = 0;
 123                 else
 124                         ins = 1;
 125         }
 126         return ins;
 127 }
 128 
 129 int cpci_check_ext(struct slot *slot)
 130 {
 131         int hs_cap;
 132         u16 hs_csr;
 133         int ext = 0;
 134 
 135         hs_cap = pci_bus_find_capability(slot->bus,
 136                                          slot->devfn,
 137                                          PCI_CAP_ID_CHSWP);
 138         if (!hs_cap)
 139                 return 0;
 140         if (pci_bus_read_config_word(slot->bus,
 141                                      slot->devfn,
 142                                      hs_cap + 2,
 143                                      &hs_csr))
 144                 return 0;
 145         if (hs_csr & HS_CSR_EXT)
 146                 ext = 1;
 147         return ext;
 148 }
 149 
 150 int cpci_clear_ext(struct slot *slot)
 151 {
 152         int hs_cap;
 153         u16 hs_csr;
 154 
 155         hs_cap = pci_bus_find_capability(slot->bus,
 156                                          slot->devfn,
 157                                          PCI_CAP_ID_CHSWP);
 158         if (!hs_cap)
 159                 return -ENODEV;
 160         if (pci_bus_read_config_word(slot->bus,
 161                                      slot->devfn,
 162                                      hs_cap + 2,
 163                                      &hs_csr))
 164                 return -ENODEV;
 165         if (hs_csr & HS_CSR_EXT) {
 166                 /* Clear EXT (by setting it) */
 167                 if (pci_bus_write_config_word(slot->bus,
 168                                               slot->devfn,
 169                                               hs_cap + 2,
 170                                               hs_csr))
 171                         return -ENODEV;
 172         }
 173         return 0;
 174 }
 175 
 176 int cpci_led_on(struct slot *slot)
 177 {
 178         int hs_cap;
 179         u16 hs_csr;
 180 
 181         hs_cap = pci_bus_find_capability(slot->bus,
 182                                          slot->devfn,
 183                                          PCI_CAP_ID_CHSWP);
 184         if (!hs_cap)
 185                 return -ENODEV;
 186         if (pci_bus_read_config_word(slot->bus,
 187                                      slot->devfn,
 188                                      hs_cap + 2,
 189                                      &hs_csr))
 190                 return -ENODEV;
 191         if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
 192                 hs_csr |= HS_CSR_LOO;
 193                 if (pci_bus_write_config_word(slot->bus,
 194                                               slot->devfn,
 195                                               hs_cap + 2,
 196                                               hs_csr)) {
 197                         err("Could not set LOO for slot %s", slot_name(slot));
 198                         return -ENODEV;
 199                 }
 200         }
 201         return 0;
 202 }
 203 
 204 int cpci_led_off(struct slot *slot)
 205 {
 206         int hs_cap;
 207         u16 hs_csr;
 208 
 209         hs_cap = pci_bus_find_capability(slot->bus,
 210                                          slot->devfn,
 211                                          PCI_CAP_ID_CHSWP);
 212         if (!hs_cap)
 213                 return -ENODEV;
 214         if (pci_bus_read_config_word(slot->bus,
 215                                      slot->devfn,
 216                                      hs_cap + 2,
 217                                      &hs_csr))
 218                 return -ENODEV;
 219         if (hs_csr & HS_CSR_LOO) {
 220                 hs_csr &= ~HS_CSR_LOO;
 221                 if (pci_bus_write_config_word(slot->bus,
 222                                               slot->devfn,
 223                                               hs_cap + 2,
 224                                               hs_csr)) {
 225                         err("Could not clear LOO for slot %s", slot_name(slot));
 226                         return -ENODEV;
 227                 }
 228         }
 229         return 0;
 230 }
 231 
 232 
 233 /*
 234  * Device configuration functions
 235  */
 236 
 237 int cpci_configure_slot(struct slot *slot)
 238 {
 239         struct pci_dev *dev;
 240         struct pci_bus *parent;
 241         int ret = 0;
 242 
 243         dbg("%s - enter", __func__);
 244 
 245         pci_lock_rescan_remove();
 246 
 247         if (slot->dev == NULL) {
 248                 dbg("pci_dev null, finding %02x:%02x:%x",
 249                     slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
 250                 slot->dev = pci_get_slot(slot->bus, slot->devfn);
 251         }
 252 
 253         /* Still NULL? Well then scan for it! */
 254         if (slot->dev == NULL) {
 255                 int n;
 256                 dbg("pci_dev still null");
 257 
 258                 /*
 259                  * This will generate pci_dev structures for all functions, but
 260                  * we will only call this case when lookup fails.
 261                  */
 262                 n = pci_scan_slot(slot->bus, slot->devfn);
 263                 dbg("%s: pci_scan_slot returned %d", __func__, n);
 264                 slot->dev = pci_get_slot(slot->bus, slot->devfn);
 265                 if (slot->dev == NULL) {
 266                         err("Could not find PCI device for slot %02x", slot->number);
 267                         ret = -ENODEV;
 268                         goto out;
 269                 }
 270         }
 271         parent = slot->dev->bus;
 272 
 273         for_each_pci_bridge(dev, parent) {
 274                 if (PCI_SLOT(dev->devfn) == PCI_SLOT(slot->devfn))
 275                         pci_hp_add_bridge(dev);
 276         }
 277 
 278         pci_assign_unassigned_bridge_resources(parent->self);
 279 
 280         pci_bus_add_devices(parent);
 281 
 282  out:
 283         pci_unlock_rescan_remove();
 284         dbg("%s - exit", __func__);
 285         return ret;
 286 }
 287 
 288 int cpci_unconfigure_slot(struct slot *slot)
 289 {
 290         struct pci_dev *dev, *temp;
 291 
 292         dbg("%s - enter", __func__);
 293         if (!slot->dev) {
 294                 err("No device for slot %02x\n", slot->number);
 295                 return -ENODEV;
 296         }
 297 
 298         pci_lock_rescan_remove();
 299 
 300         list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
 301                 if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
 302                         continue;
 303                 pci_dev_get(dev);
 304                 pci_stop_and_remove_bus_device(dev);
 305                 pci_dev_put(dev);
 306         }
 307         pci_dev_put(slot->dev);
 308         slot->dev = NULL;
 309 
 310         pci_unlock_rescan_remove();
 311 
 312         dbg("%s - exit", __func__);
 313         return 0;
 314 }

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