LCOV - code coverage report
Current view: top level - drivers/base - transport_class.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 73 0.0 %
Date: 2023-03-27 20:00:47 Functions: 0 15 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * transport_class.c - implementation of generic transport classes
       4             :  *                     using attribute_containers
       5             :  *
       6             :  * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
       7             :  *
       8             :  * The basic idea here is to allow any "device controller" (which
       9             :  * would most often be a Host Bus Adapter to use the services of one
      10             :  * or more tranport classes for performing transport specific
      11             :  * services.  Transport specific services are things that the generic
      12             :  * command layer doesn't want to know about (speed settings, line
      13             :  * condidtioning, etc), but which the user might be interested in.
      14             :  * Thus, the HBA's use the routines exported by the transport classes
      15             :  * to perform these functions.  The transport classes export certain
      16             :  * values to the user via sysfs using attribute containers.
      17             :  *
      18             :  * Note: because not every HBA will care about every transport
      19             :  * attribute, there's a many to one relationship that goes like this:
      20             :  *
      21             :  * transport class<-----attribute container<----class device
      22             :  *
      23             :  * Usually the attribute container is per-HBA, but the design doesn't
      24             :  * mandate that.  Although most of the services will be specific to
      25             :  * the actual external storage connection used by the HBA, the generic
      26             :  * transport class is framed entirely in terms of generic devices to
      27             :  * allow it to be used by any physical HBA in the system.
      28             :  */
      29             : #include <linux/export.h>
      30             : #include <linux/attribute_container.h>
      31             : #include <linux/transport_class.h>
      32             : 
      33             : static int transport_remove_classdev(struct attribute_container *cont,
      34             :                                      struct device *dev,
      35             :                                      struct device *classdev);
      36             : 
      37             : /**
      38             :  * transport_class_register - register an initial transport class
      39             :  *
      40             :  * @tclass:     a pointer to the transport class structure to be initialised
      41             :  *
      42             :  * The transport class contains an embedded class which is used to
      43             :  * identify it.  The caller should initialise this structure with
      44             :  * zeros and then generic class must have been initialised with the
      45             :  * actual transport class unique name.  There's a macro
      46             :  * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
      47             :  * be registered).
      48             :  *
      49             :  * Returns 0 on success or error on failure.
      50             :  */
      51           0 : int transport_class_register(struct transport_class *tclass)
      52             : {
      53           0 :         return class_register(&tclass->class);
      54             : }
      55             : EXPORT_SYMBOL_GPL(transport_class_register);
      56             : 
      57             : /**
      58             :  * transport_class_unregister - unregister a previously registered class
      59             :  *
      60             :  * @tclass: The transport class to unregister
      61             :  *
      62             :  * Must be called prior to deallocating the memory for the transport
      63             :  * class.
      64             :  */
      65           0 : void transport_class_unregister(struct transport_class *tclass)
      66             : {
      67           0 :         class_unregister(&tclass->class);
      68           0 : }
      69             : EXPORT_SYMBOL_GPL(transport_class_unregister);
      70             : 
      71           0 : static int anon_transport_dummy_function(struct transport_container *tc,
      72             :                                          struct device *dev,
      73             :                                          struct device *cdev)
      74             : {
      75             :         /* do nothing */
      76           0 :         return 0;
      77             : }
      78             : 
      79             : /**
      80             :  * anon_transport_class_register - register an anonymous class
      81             :  *
      82             :  * @atc: The anon transport class to register
      83             :  *
      84             :  * The anonymous transport class contains both a transport class and a
      85             :  * container.  The idea of an anonymous class is that it never
      86             :  * actually has any device attributes associated with it (and thus
      87             :  * saves on container storage).  So it can only be used for triggering
      88             :  * events.  Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
      89             :  * initialise the anon transport class storage.
      90             :  */
      91           0 : int anon_transport_class_register(struct anon_transport_class *atc)
      92             : {
      93             :         int error;
      94           0 :         atc->container.class = &atc->tclass.class;
      95           0 :         attribute_container_set_no_classdevs(&atc->container);
      96           0 :         error = attribute_container_register(&atc->container);
      97           0 :         if (error)
      98             :                 return error;
      99           0 :         atc->tclass.setup = anon_transport_dummy_function;
     100           0 :         atc->tclass.remove = anon_transport_dummy_function;
     101           0 :         return 0;
     102             : }
     103             : EXPORT_SYMBOL_GPL(anon_transport_class_register);
     104             : 
     105             : /**
     106             :  * anon_transport_class_unregister - unregister an anon class
     107             :  *
     108             :  * @atc: Pointer to the anon transport class to unregister
     109             :  *
     110             :  * Must be called prior to deallocating the memory for the anon
     111             :  * transport class.
     112             :  */
     113           0 : void anon_transport_class_unregister(struct anon_transport_class *atc)
     114             : {
     115           0 :         if (unlikely(attribute_container_unregister(&atc->container)))
     116           0 :                 BUG();
     117           0 : }
     118             : EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
     119             : 
     120           0 : static int transport_setup_classdev(struct attribute_container *cont,
     121             :                                     struct device *dev,
     122             :                                     struct device *classdev)
     123             : {
     124           0 :         struct transport_class *tclass = class_to_transport_class(cont->class);
     125           0 :         struct transport_container *tcont = attribute_container_to_transport_container(cont);
     126             : 
     127           0 :         if (tclass->setup)
     128           0 :                 tclass->setup(tcont, dev, classdev);
     129             : 
     130           0 :         return 0;
     131             : }
     132             : 
     133             : /**
     134             :  * transport_setup_device - declare a new dev for transport class association but don't make it visible yet.
     135             :  * @dev: the generic device representing the entity being added
     136             :  *
     137             :  * Usually, dev represents some component in the HBA system (either
     138             :  * the HBA itself or a device remote across the HBA bus).  This
     139             :  * routine is simply a trigger point to see if any set of transport
     140             :  * classes wishes to associate with the added device.  This allocates
     141             :  * storage for the class device and initialises it, but does not yet
     142             :  * add it to the system or add attributes to it (you do this with
     143             :  * transport_add_device).  If you have no need for a separate setup
     144             :  * and add operations, use transport_register_device (see
     145             :  * transport_class.h).
     146             :  */
     147             : 
     148           0 : void transport_setup_device(struct device *dev)
     149             : {
     150           0 :         attribute_container_add_device(dev, transport_setup_classdev);
     151           0 : }
     152             : EXPORT_SYMBOL_GPL(transport_setup_device);
     153             : 
     154           0 : static int transport_add_class_device(struct attribute_container *cont,
     155             :                                       struct device *dev,
     156             :                                       struct device *classdev)
     157             : {
     158           0 :         struct transport_class *tclass = class_to_transport_class(cont->class);
     159           0 :         int error = attribute_container_add_class_device(classdev);
     160           0 :         struct transport_container *tcont = 
     161           0 :                 attribute_container_to_transport_container(cont);
     162             : 
     163           0 :         if (error)
     164             :                 goto err_remove;
     165             : 
     166           0 :         if (tcont->statistics) {
     167           0 :                 error = sysfs_create_group(&classdev->kobj, tcont->statistics);
     168           0 :                 if (error)
     169             :                         goto err_del;
     170             :         }
     171             : 
     172             :         return 0;
     173             : 
     174             : err_del:
     175           0 :         attribute_container_class_device_del(classdev);
     176             : err_remove:
     177           0 :         if (tclass->remove)
     178           0 :                 tclass->remove(tcont, dev, classdev);
     179             : 
     180             :         return error;
     181             : }
     182             : 
     183             : 
     184             : /**
     185             :  * transport_add_device - declare a new dev for transport class association
     186             :  *
     187             :  * @dev: the generic device representing the entity being added
     188             :  *
     189             :  * Usually, dev represents some component in the HBA system (either
     190             :  * the HBA itself or a device remote across the HBA bus).  This
     191             :  * routine is simply a trigger point used to add the device to the
     192             :  * system and register attributes for it.
     193             :  */
     194           0 : int transport_add_device(struct device *dev)
     195             : {
     196           0 :         return attribute_container_device_trigger_safe(dev,
     197             :                                         transport_add_class_device,
     198             :                                         transport_remove_classdev);
     199             : }
     200             : EXPORT_SYMBOL_GPL(transport_add_device);
     201             : 
     202           0 : static int transport_configure(struct attribute_container *cont,
     203             :                                struct device *dev,
     204             :                                struct device *cdev)
     205             : {
     206           0 :         struct transport_class *tclass = class_to_transport_class(cont->class);
     207           0 :         struct transport_container *tcont = attribute_container_to_transport_container(cont);
     208             : 
     209           0 :         if (tclass->configure)
     210           0 :                 tclass->configure(tcont, dev, cdev);
     211             : 
     212           0 :         return 0;
     213             : }
     214             : 
     215             : /**
     216             :  * transport_configure_device - configure an already set up device
     217             :  *
     218             :  * @dev: generic device representing device to be configured
     219             :  *
     220             :  * The idea of configure is simply to provide a point within the setup
     221             :  * process to allow the transport class to extract information from a
     222             :  * device after it has been setup.  This is used in SCSI because we
     223             :  * have to have a setup device to begin using the HBA, but after we
     224             :  * send the initial inquiry, we use configure to extract the device
     225             :  * parameters.  The device need not have been added to be configured.
     226             :  */
     227           0 : void transport_configure_device(struct device *dev)
     228             : {
     229           0 :         attribute_container_device_trigger(dev, transport_configure);
     230           0 : }
     231             : EXPORT_SYMBOL_GPL(transport_configure_device);
     232             : 
     233           0 : static int transport_remove_classdev(struct attribute_container *cont,
     234             :                                      struct device *dev,
     235             :                                      struct device *classdev)
     236             : {
     237           0 :         struct transport_container *tcont = 
     238           0 :                 attribute_container_to_transport_container(cont);
     239           0 :         struct transport_class *tclass = class_to_transport_class(cont->class);
     240             : 
     241           0 :         if (tclass->remove)
     242           0 :                 tclass->remove(tcont, dev, classdev);
     243             : 
     244           0 :         if (tclass->remove != anon_transport_dummy_function) {
     245           0 :                 if (tcont->statistics)
     246           0 :                         sysfs_remove_group(&classdev->kobj, tcont->statistics);
     247           0 :                 attribute_container_class_device_del(classdev);
     248             :         }
     249             : 
     250           0 :         return 0;
     251             : }
     252             : 
     253             : 
     254             : /**
     255             :  * transport_remove_device - remove the visibility of a device
     256             :  *
     257             :  * @dev: generic device to remove
     258             :  *
     259             :  * This call removes the visibility of the device (to the user from
     260             :  * sysfs), but does not destroy it.  To eliminate a device entirely
     261             :  * you must also call transport_destroy_device.  If you don't need to
     262             :  * do remove and destroy as separate operations, use
     263             :  * transport_unregister_device() (see transport_class.h) which will
     264             :  * perform both calls for you.
     265             :  */
     266           0 : void transport_remove_device(struct device *dev)
     267             : {
     268           0 :         attribute_container_device_trigger(dev, transport_remove_classdev);
     269           0 : }
     270             : EXPORT_SYMBOL_GPL(transport_remove_device);
     271             : 
     272           0 : static void transport_destroy_classdev(struct attribute_container *cont,
     273             :                                       struct device *dev,
     274             :                                       struct device *classdev)
     275             : {
     276           0 :         struct transport_class *tclass = class_to_transport_class(cont->class);
     277             : 
     278           0 :         if (tclass->remove != anon_transport_dummy_function)
     279           0 :                 put_device(classdev);
     280           0 : }
     281             : 
     282             : 
     283             : /**
     284             :  * transport_destroy_device - destroy a removed device
     285             :  *
     286             :  * @dev: device to eliminate from the transport class.
     287             :  *
     288             :  * This call triggers the elimination of storage associated with the
     289             :  * transport classdev.  Note: all it really does is relinquish a
     290             :  * reference to the classdev.  The memory will not be freed until the
     291             :  * last reference goes to zero.  Note also that the classdev retains a
     292             :  * reference count on dev, so dev too will remain for as long as the
     293             :  * transport class device remains around.
     294             :  */
     295           0 : void transport_destroy_device(struct device *dev)
     296             : {
     297           0 :         attribute_container_remove_device(dev, transport_destroy_classdev);
     298           0 : }
     299             : EXPORT_SYMBOL_GPL(transport_destroy_device);

Generated by: LCOV version 1.14