Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * transport_class.c - implementation of generic transport classes
0004  *                     using attribute_containers
0005  *
0006  * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
0007  *
0008  * The basic idea here is to allow any "device controller" (which
0009  * would most often be a Host Bus Adapter to use the services of one
0010  * or more tranport classes for performing transport specific
0011  * services.  Transport specific services are things that the generic
0012  * command layer doesn't want to know about (speed settings, line
0013  * condidtioning, etc), but which the user might be interested in.
0014  * Thus, the HBA's use the routines exported by the transport classes
0015  * to perform these functions.  The transport classes export certain
0016  * values to the user via sysfs using attribute containers.
0017  *
0018  * Note: because not every HBA will care about every transport
0019  * attribute, there's a many to one relationship that goes like this:
0020  *
0021  * transport class<-----attribute container<----class device
0022  *
0023  * Usually the attribute container is per-HBA, but the design doesn't
0024  * mandate that.  Although most of the services will be specific to
0025  * the actual external storage connection used by the HBA, the generic
0026  * transport class is framed entirely in terms of generic devices to
0027  * allow it to be used by any physical HBA in the system.
0028  */
0029 #include <linux/export.h>
0030 #include <linux/attribute_container.h>
0031 #include <linux/transport_class.h>
0032 
0033 static int transport_remove_classdev(struct attribute_container *cont,
0034                      struct device *dev,
0035                      struct device *classdev);
0036 
0037 /**
0038  * transport_class_register - register an initial transport class
0039  *
0040  * @tclass: a pointer to the transport class structure to be initialised
0041  *
0042  * The transport class contains an embedded class which is used to
0043  * identify it.  The caller should initialise this structure with
0044  * zeros and then generic class must have been initialised with the
0045  * actual transport class unique name.  There's a macro
0046  * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
0047  * be registered).
0048  *
0049  * Returns 0 on success or error on failure.
0050  */
0051 int transport_class_register(struct transport_class *tclass)
0052 {
0053     return class_register(&tclass->class);
0054 }
0055 EXPORT_SYMBOL_GPL(transport_class_register);
0056 
0057 /**
0058  * transport_class_unregister - unregister a previously registered class
0059  *
0060  * @tclass: The transport class to unregister
0061  *
0062  * Must be called prior to deallocating the memory for the transport
0063  * class.
0064  */
0065 void transport_class_unregister(struct transport_class *tclass)
0066 {
0067     class_unregister(&tclass->class);
0068 }
0069 EXPORT_SYMBOL_GPL(transport_class_unregister);
0070 
0071 static int anon_transport_dummy_function(struct transport_container *tc,
0072                      struct device *dev,
0073                      struct device *cdev)
0074 {
0075     /* do nothing */
0076     return 0;
0077 }
0078 
0079 /**
0080  * anon_transport_class_register - register an anonymous class
0081  *
0082  * @atc: The anon transport class to register
0083  *
0084  * The anonymous transport class contains both a transport class and a
0085  * container.  The idea of an anonymous class is that it never
0086  * actually has any device attributes associated with it (and thus
0087  * saves on container storage).  So it can only be used for triggering
0088  * events.  Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
0089  * initialise the anon transport class storage.
0090  */
0091 int anon_transport_class_register(struct anon_transport_class *atc)
0092 {
0093     int error;
0094     atc->container.class = &atc->tclass.class;
0095     attribute_container_set_no_classdevs(&atc->container);
0096     error = attribute_container_register(&atc->container);
0097     if (error)
0098         return error;
0099     atc->tclass.setup = anon_transport_dummy_function;
0100     atc->tclass.remove = anon_transport_dummy_function;
0101     return 0;
0102 }
0103 EXPORT_SYMBOL_GPL(anon_transport_class_register);
0104 
0105 /**
0106  * anon_transport_class_unregister - unregister an anon class
0107  *
0108  * @atc: Pointer to the anon transport class to unregister
0109  *
0110  * Must be called prior to deallocating the memory for the anon
0111  * transport class.
0112  */
0113 void anon_transport_class_unregister(struct anon_transport_class *atc)
0114 {
0115     if (unlikely(attribute_container_unregister(&atc->container)))
0116         BUG();
0117 }
0118 EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
0119 
0120 static int transport_setup_classdev(struct attribute_container *cont,
0121                     struct device *dev,
0122                     struct device *classdev)
0123 {
0124     struct transport_class *tclass = class_to_transport_class(cont->class);
0125     struct transport_container *tcont = attribute_container_to_transport_container(cont);
0126 
0127     if (tclass->setup)
0128         tclass->setup(tcont, dev, classdev);
0129 
0130     return 0;
0131 }
0132 
0133 /**
0134  * transport_setup_device - declare a new dev for transport class association but don't make it visible yet.
0135  * @dev: the generic device representing the entity being added
0136  *
0137  * Usually, dev represents some component in the HBA system (either
0138  * the HBA itself or a device remote across the HBA bus).  This
0139  * routine is simply a trigger point to see if any set of transport
0140  * classes wishes to associate with the added device.  This allocates
0141  * storage for the class device and initialises it, but does not yet
0142  * add it to the system or add attributes to it (you do this with
0143  * transport_add_device).  If you have no need for a separate setup
0144  * and add operations, use transport_register_device (see
0145  * transport_class.h).
0146  */
0147 
0148 void transport_setup_device(struct device *dev)
0149 {
0150     attribute_container_add_device(dev, transport_setup_classdev);
0151 }
0152 EXPORT_SYMBOL_GPL(transport_setup_device);
0153 
0154 static int transport_add_class_device(struct attribute_container *cont,
0155                       struct device *dev,
0156                       struct device *classdev)
0157 {
0158     int error = attribute_container_add_class_device(classdev);
0159     struct transport_container *tcont = 
0160         attribute_container_to_transport_container(cont);
0161 
0162     if (!error && tcont->statistics)
0163         error = sysfs_create_group(&classdev->kobj, tcont->statistics);
0164 
0165     return error;
0166 }
0167 
0168 
0169 /**
0170  * transport_add_device - declare a new dev for transport class association
0171  *
0172  * @dev: the generic device representing the entity being added
0173  *
0174  * Usually, dev represents some component in the HBA system (either
0175  * the HBA itself or a device remote across the HBA bus).  This
0176  * routine is simply a trigger point used to add the device to the
0177  * system and register attributes for it.
0178  */
0179 int transport_add_device(struct device *dev)
0180 {
0181     return attribute_container_device_trigger_safe(dev,
0182                     transport_add_class_device,
0183                     transport_remove_classdev);
0184 }
0185 EXPORT_SYMBOL_GPL(transport_add_device);
0186 
0187 static int transport_configure(struct attribute_container *cont,
0188                    struct device *dev,
0189                    struct device *cdev)
0190 {
0191     struct transport_class *tclass = class_to_transport_class(cont->class);
0192     struct transport_container *tcont = attribute_container_to_transport_container(cont);
0193 
0194     if (tclass->configure)
0195         tclass->configure(tcont, dev, cdev);
0196 
0197     return 0;
0198 }
0199 
0200 /**
0201  * transport_configure_device - configure an already set up device
0202  *
0203  * @dev: generic device representing device to be configured
0204  *
0205  * The idea of configure is simply to provide a point within the setup
0206  * process to allow the transport class to extract information from a
0207  * device after it has been setup.  This is used in SCSI because we
0208  * have to have a setup device to begin using the HBA, but after we
0209  * send the initial inquiry, we use configure to extract the device
0210  * parameters.  The device need not have been added to be configured.
0211  */
0212 void transport_configure_device(struct device *dev)
0213 {
0214     attribute_container_device_trigger(dev, transport_configure);
0215 }
0216 EXPORT_SYMBOL_GPL(transport_configure_device);
0217 
0218 static int transport_remove_classdev(struct attribute_container *cont,
0219                      struct device *dev,
0220                      struct device *classdev)
0221 {
0222     struct transport_container *tcont = 
0223         attribute_container_to_transport_container(cont);
0224     struct transport_class *tclass = class_to_transport_class(cont->class);
0225 
0226     if (tclass->remove)
0227         tclass->remove(tcont, dev, classdev);
0228 
0229     if (tclass->remove != anon_transport_dummy_function) {
0230         if (tcont->statistics)
0231             sysfs_remove_group(&classdev->kobj, tcont->statistics);
0232         attribute_container_class_device_del(classdev);
0233     }
0234 
0235     return 0;
0236 }
0237 
0238 
0239 /**
0240  * transport_remove_device - remove the visibility of a device
0241  *
0242  * @dev: generic device to remove
0243  *
0244  * This call removes the visibility of the device (to the user from
0245  * sysfs), but does not destroy it.  To eliminate a device entirely
0246  * you must also call transport_destroy_device.  If you don't need to
0247  * do remove and destroy as separate operations, use
0248  * transport_unregister_device() (see transport_class.h) which will
0249  * perform both calls for you.
0250  */
0251 void transport_remove_device(struct device *dev)
0252 {
0253     attribute_container_device_trigger(dev, transport_remove_classdev);
0254 }
0255 EXPORT_SYMBOL_GPL(transport_remove_device);
0256 
0257 static void transport_destroy_classdev(struct attribute_container *cont,
0258                       struct device *dev,
0259                       struct device *classdev)
0260 {
0261     struct transport_class *tclass = class_to_transport_class(cont->class);
0262 
0263     if (tclass->remove != anon_transport_dummy_function)
0264         put_device(classdev);
0265 }
0266 
0267 
0268 /**
0269  * transport_destroy_device - destroy a removed device
0270  *
0271  * @dev: device to eliminate from the transport class.
0272  *
0273  * This call triggers the elimination of storage associated with the
0274  * transport classdev.  Note: all it really does is relinquish a
0275  * reference to the classdev.  The memory will not be freed until the
0276  * last reference goes to zero.  Note also that the classdev retains a
0277  * reference count on dev, so dev too will remain for as long as the
0278  * transport class device remains around.
0279  */
0280 void transport_destroy_device(struct device *dev)
0281 {
0282     attribute_container_remove_device(dev, transport_destroy_classdev);
0283 }
0284 EXPORT_SYMBOL_GPL(transport_destroy_device);