root/drivers/staging/uwb/umc-bus.c

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

DEFINITIONS

This source file includes following definitions.
  1. umc_bus_pre_reset_helper
  2. umc_bus_post_reset_helper
  3. umc_controller_reset
  4. umc_match_pci_id
  5. umc_bus_rescan_helper
  6. umc_bus_rescan
  7. umc_bus_match
  8. umc_device_probe
  9. umc_device_remove
  10. capability_id_show
  11. version_show
  12. umc_bus_init
  13. umc_bus_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Bus for UWB Multi-interface Controller capabilities.
   4  *
   5  * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/sysfs.h>
   9 #include <linux/workqueue.h>
  10 #include <linux/module.h>
  11 #include <linux/pci.h>
  12 #include "include/umc.h"
  13 
  14 static int umc_bus_pre_reset_helper(struct device *dev, void *data)
  15 {
  16         int ret = 0;
  17 
  18         if (dev->driver) {
  19                 struct umc_dev *umc = to_umc_dev(dev);
  20                 struct umc_driver *umc_drv = to_umc_driver(dev->driver);
  21 
  22                 if (umc_drv->pre_reset)
  23                         ret = umc_drv->pre_reset(umc);
  24                 else
  25                         device_release_driver(dev);
  26         }
  27         return ret;
  28 }
  29 
  30 static int umc_bus_post_reset_helper(struct device *dev, void *data)
  31 {
  32         int ret = 0;
  33 
  34         if (dev->driver) {
  35                 struct umc_dev *umc = to_umc_dev(dev);
  36                 struct umc_driver *umc_drv = to_umc_driver(dev->driver);
  37 
  38                 if (umc_drv->post_reset)
  39                         ret = umc_drv->post_reset(umc);
  40         } else
  41                 ret = device_attach(dev);
  42 
  43         return ret;
  44 }
  45 
  46 /**
  47  * umc_controller_reset - reset the whole UMC controller
  48  * @umc: the UMC device for the radio controller.
  49  *
  50  * Drivers or all capabilities of the controller will have their
  51  * pre_reset methods called or be unbound from their device.  Then all
  52  * post_reset methods will be called or the drivers will be rebound.
  53  *
  54  * Radio controllers must provide pre_reset and post_reset methods and
  55  * reset the hardware in their start method.
  56  *
  57  * If this is called while a probe() or remove() is in progress it
  58  * will return -EAGAIN and not perform the reset.
  59  */
  60 int umc_controller_reset(struct umc_dev *umc)
  61 {
  62         struct device *parent = umc->dev.parent;
  63         int ret = 0;
  64 
  65         if (!device_trylock(parent))
  66                 return -EAGAIN;
  67         ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
  68         if (ret >= 0)
  69                 ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper);
  70         device_unlock(parent);
  71 
  72         return ret;
  73 }
  74 EXPORT_SYMBOL_GPL(umc_controller_reset);
  75 
  76 /**
  77  * umc_match_pci_id - match a UMC driver to a UMC device's parent PCI device.
  78  * @umc_drv: umc driver with match_data pointing to a zero-terminated
  79  * table of pci_device_id's.
  80  * @umc: umc device whose parent is to be matched.
  81  */
  82 int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc)
  83 {
  84         const struct pci_device_id *id_table = umc_drv->match_data;
  85         struct pci_dev *pci;
  86 
  87         if (!dev_is_pci(umc->dev.parent))
  88                 return 0;
  89 
  90         pci = to_pci_dev(umc->dev.parent);
  91         return pci_match_id(id_table, pci) != NULL;
  92 }
  93 EXPORT_SYMBOL_GPL(umc_match_pci_id);
  94 
  95 static int umc_bus_rescan_helper(struct device *dev, void *data)
  96 {
  97         int ret = 0;
  98 
  99         if (!dev->driver)
 100                 ret = device_attach(dev);
 101 
 102         return ret;
 103 }
 104 
 105 static void umc_bus_rescan(struct device *parent)
 106 {
 107         int err;
 108 
 109         /*
 110          * We can't use bus_rescan_devices() here as it deadlocks when
 111          * it tries to retake the dev->parent semaphore.
 112          */
 113         err = device_for_each_child(parent, NULL, umc_bus_rescan_helper);
 114         if (err < 0)
 115                 printk(KERN_WARNING "%s: rescan of bus failed: %d\n",
 116                        KBUILD_MODNAME, err);
 117 }
 118 
 119 static int umc_bus_match(struct device *dev, struct device_driver *drv)
 120 {
 121         struct umc_dev *umc = to_umc_dev(dev);
 122         struct umc_driver *umc_driver = to_umc_driver(drv);
 123 
 124         if (umc->cap_id == umc_driver->cap_id) {
 125                 if (umc_driver->match)
 126                         return umc_driver->match(umc_driver, umc);
 127                 else
 128                         return 1;
 129         }
 130         return 0;
 131 }
 132 
 133 static int umc_device_probe(struct device *dev)
 134 {
 135         struct umc_dev *umc;
 136         struct umc_driver *umc_driver;
 137         int err;
 138 
 139         umc_driver = to_umc_driver(dev->driver);
 140         umc = to_umc_dev(dev);
 141 
 142         get_device(dev);
 143         err = umc_driver->probe(umc);
 144         if (err)
 145                 put_device(dev);
 146         else
 147                 umc_bus_rescan(dev->parent);
 148 
 149         return err;
 150 }
 151 
 152 static int umc_device_remove(struct device *dev)
 153 {
 154         struct umc_dev *umc;
 155         struct umc_driver *umc_driver;
 156 
 157         umc_driver = to_umc_driver(dev->driver);
 158         umc = to_umc_dev(dev);
 159 
 160         umc_driver->remove(umc);
 161         put_device(dev);
 162         return 0;
 163 }
 164 
 165 static ssize_t capability_id_show(struct device *dev, struct device_attribute *attr, char *buf)
 166 {
 167         struct umc_dev *umc = to_umc_dev(dev);
 168 
 169         return sprintf(buf, "0x%02x\n", umc->cap_id);
 170 }
 171 static DEVICE_ATTR_RO(capability_id);
 172 
 173 static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
 174 {
 175         struct umc_dev *umc = to_umc_dev(dev);
 176 
 177         return sprintf(buf, "0x%04x\n", umc->version);
 178 }
 179 static DEVICE_ATTR_RO(version);
 180 
 181 static struct attribute *umc_dev_attrs[] = {
 182         &dev_attr_capability_id.attr,
 183         &dev_attr_version.attr,
 184         NULL,
 185 };
 186 ATTRIBUTE_GROUPS(umc_dev);
 187 
 188 struct bus_type umc_bus_type = {
 189         .name           = "umc",
 190         .match          = umc_bus_match,
 191         .probe          = umc_device_probe,
 192         .remove         = umc_device_remove,
 193         .dev_groups     = umc_dev_groups,
 194 };
 195 EXPORT_SYMBOL_GPL(umc_bus_type);
 196 
 197 static int __init umc_bus_init(void)
 198 {
 199         return bus_register(&umc_bus_type);
 200 }
 201 module_init(umc_bus_init);
 202 
 203 static void __exit umc_bus_exit(void)
 204 {
 205         bus_unregister(&umc_bus_type);
 206 }
 207 module_exit(umc_bus_exit);
 208 
 209 MODULE_DESCRIPTION("UWB Multi-interface Controller capability bus");
 210 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
 211 MODULE_LICENSE("GPL");

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