11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_class.c - implementation of generic transport classes 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * using attribute_containers 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is licensed under GPLv2 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The basic idea here is to allow any "device controller" (which 10ebd8bb7647e908e8654e565fa289b0300f9f8fa7James Bottomley * would most often be a Host Bus Adapter to use the services of one 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or more tranport classes for performing transport specific 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * services. Transport specific services are things that the generic 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command layer doesn't want to know about (speed settings, line 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condidtioning, etc), but which the user might be interested in. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, the HBA's use the routines exported by the transport classes 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to perform these functions. The transport classes export certain 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * values to the user via sysfs using attribute containers. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: because not every HBA will care about every transport 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attribute, there's a many to one relationship that goes like this: 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport class<-----attribute container<----class device 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Usually the attribute container is per-HBA, but the design doesn't 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mandate that. Although most of the services will be specific to 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the actual external storage connection used by the HBA, the generic 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport class is framed entirely in terms of generic devices to 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allow it to be used by any physical HBA in the system. 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 30eef9c3d90bafa1cb0dd397cee400fab21b39abfePaul Gortmaker#include <linux/export.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/attribute_container.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/transport_class.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_class_register - register an initial transport class 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @tclass: a pointer to the transport class structure to be initialised 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The transport class contains an embedded class which is used to 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * identify it. The caller should initialise this structure with 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zeros and then generic class must have been initialised with the 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actual transport class unique name. There's a macro 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be registered). 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns 0 on success or error on failure. 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint transport_class_register(struct transport_class *tclass) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return class_register(&tclass->class); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_class_register); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_class_unregister - unregister a previously registered class 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @tclass: The transport class to unregister 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called prior to deallocating the memory for the transport 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * class. 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_class_unregister(struct transport_class *tclass) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds class_unregister(&tclass->class); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_class_unregister); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68d0a7e574007fd547d72ec693bfa35778623d0738James Bottomleystatic int anon_transport_dummy_function(struct transport_container *tc, 69d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley struct device *dev, 70ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *cdev) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do nothing */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anon_transport_class_register - register an anonymous class 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @atc: The anon transport class to register 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The anonymous transport class contains both a transport class and a 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * container. The idea of an anonymous class is that it never 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually has any device attributes associated with it (and thus 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * saves on container storage). So it can only be used for triggering 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * events. Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initialise the anon transport class storage. 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint anon_transport_class_register(struct anon_transport_class *atc) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atc->container.class = &atc->tclass.class; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_set_no_classdevs(&atc->container); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = attribute_container_register(&atc->container); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atc->tclass.setup = anon_transport_dummy_function; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atc->tclass.remove = anon_transport_dummy_function; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(anon_transport_class_register); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anon_transport_class_unregister - unregister an anon class 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @atc: Pointer to the anon transport class to unregister 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called prior to deallocating the memory for the anon 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport class. 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid anon_transport_class_unregister(struct anon_transport_class *atc) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1122f3edc6936e3f6be3f1df1e89c141ae028fa605eJames Bottomley if (unlikely(attribute_container_unregister(&atc->container))) 1132f3edc6936e3f6be3f1df1e89c141ae028fa605eJames Bottomley BUG(); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(anon_transport_class_unregister); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int transport_setup_classdev(struct attribute_container *cont, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev, 119ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *classdev) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_class *tclass = class_to_transport_class(cont->class); 122d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley struct transport_container *tcont = attribute_container_to_transport_container(cont); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tclass->setup) 125d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley tclass->setup(tcont, dev, classdev); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1310643245f595dc175c14245fa1e1e9efda3e12f2aRandy Dunlap * transport_setup_device - declare a new dev for transport class association but don't make it visible yet. 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the generic device representing the entity being added 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Usually, dev represents some component in the HBA system (either 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the HBA itself or a device remote across the HBA bus). This 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine is simply a trigger point to see if any set of transport 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * classes wishes to associate with the added device. This allocates 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * storage for the class device and initialises it, but does not yet 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * add it to the system or add attributes to it (you do this with 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_add_device). If you have no need for a separate setup 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and add operations, use transport_register_device (see 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_class.h). 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_setup_device(struct device *dev) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_add_device(dev, transport_setup_classdev); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_setup_device); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int transport_add_class_device(struct attribute_container *cont, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev, 153ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *classdev) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = attribute_container_add_class_device(classdev); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_container *tcont = 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_to_transport_container(cont); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!error && tcont->statistics) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sysfs_create_group(&classdev->kobj, tcont->statistics); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_add_device - declare a new dev for transport class association 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the generic device representing the entity being added 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Usually, dev represents some component in the HBA system (either 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the HBA itself or a device remote across the HBA bus). This 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine is simply a trigger point used to add the device to the 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * system and register attributes for it. 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_add_device(struct device *dev) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_device_trigger(dev, transport_add_class_device); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_add_device); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int transport_configure(struct attribute_container *cont, 184d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley struct device *dev, 185ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *cdev) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_class *tclass = class_to_transport_class(cont->class); 188d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley struct transport_container *tcont = attribute_container_to_transport_container(cont); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tclass->configure) 191d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley tclass->configure(tcont, dev, cdev); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_configure_device - configure an already set up device 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: generic device representing device to be configured 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The idea of configure is simply to provide a point within the setup 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * process to allow the transport class to extract information from a 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device after it has been setup. This is used in SCSI because we 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * have to have a setup device to begin using the HBA, but after we 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send the initial inquiry, we use configure to extract the device 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameters. The device need not have been added to be configured. 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_configure_device(struct device *dev) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 210d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley attribute_container_device_trigger(dev, transport_configure); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_configure_device); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int transport_remove_classdev(struct attribute_container *cont, 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev, 216ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *classdev) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_container *tcont = 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_to_transport_container(cont); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_class *tclass = class_to_transport_class(cont->class); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tclass->remove) 223d0a7e574007fd547d72ec693bfa35778623d0738James Bottomley tclass->remove(tcont, dev, classdev); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tclass->remove != anon_transport_dummy_function) { 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tcont->statistics) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysfs_remove_group(&classdev->kobj, tcont->statistics); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_class_device_del(classdev); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_remove_device - remove the visibility of a device 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: generic device to remove 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This call removes the visibility of the device (to the user from 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs), but does not destroy it. To eliminate a device entirely 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * you must also call transport_destroy_device. If you don't need to 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do remove and destroy as separate operations, use 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_unregister_device() (see transport_class.h) which will 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perform both calls for you. 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_remove_device(struct device *dev) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_device_trigger(dev, transport_remove_classdev); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_remove_device); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void transport_destroy_classdev(struct attribute_container *cont, 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev, 255ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *classdev) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct transport_class *tclass = class_to_transport_class(cont->class); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tclass->remove != anon_transport_dummy_function) 260ee959b00c335d7780136c5abda37809191fe52c3Tony Jones put_device(classdev); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport_destroy_device - destroy a removed device 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device to eliminate from the transport class. 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This call triggers the elimination of storage associated with the 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport classdev. Note: all it really does is relinquish a 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference to the classdev. The memory will not be freed until the 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last reference goes to zero. Note also that the classdev retains a 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference count on dev, so dev too will remain for as long as the 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transport class device remains around. 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transport_destroy_device(struct device *dev) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attribute_container_remove_device(dev, transport_destroy_classdev); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(transport_destroy_device); 281