Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rapidio: add core mport removal support

Add common mport removal support functions into the RapidIO subsystem
core.

Changes to the existing mport registration process have been made to
avoid race conditions with active subsystem interfaces immediately after
mport device registration: part of initialization code from
rio_register_mport() have been moved into separate function
rio_mport_initialize() to allow to perform mport registration as the
final step of setup process.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Aurelien Jacquiot <a-jacquiot@ti.com>
Cc: Andre van Herk <andre.van.herk@prodrive-technologies.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexandre Bounine and committed by
Linus Torvalds
b77a2030 e6b585ca

+102 -24
+83 -23
drivers/rapidio/rio.c
··· 149 149 { 150 150 int err; 151 151 152 + atomic_set(&rdev->state, RIO_DEVICE_RUNNING); 152 153 err = device_register(&rdev->dev); 153 154 if (err) 154 155 return err; ··· 173 172 /* 174 173 * rio_del_device - removes a RIO device from the device model 175 174 * @rdev: RIO device 175 + * @state: device state to set during removal process 176 176 * 177 177 * Removes the RIO device to the kernel device list and subsystem's device list. 178 178 * Clears sysfs entries for the removed device. 179 179 */ 180 - void rio_del_device(struct rio_dev *rdev) 180 + void rio_del_device(struct rio_dev *rdev, enum rio_device_state state) 181 181 { 182 182 pr_debug("RIO: %s: removing %s\n", __func__, rio_name(rdev)); 183 + atomic_set(&rdev->state, state); 183 184 spin_lock(&rio_global_list_lock); 184 185 list_del(&rdev->global_list); 185 186 if (rdev->net) { ··· 2013 2010 return hdid[index]; 2014 2011 } 2015 2012 2013 + int rio_mport_initialize(struct rio_mport *mport) 2014 + { 2015 + if (next_portid >= RIO_MAX_MPORTS) { 2016 + pr_err("RIO: reached specified max number of mports\n"); 2017 + return -ENODEV; 2018 + } 2019 + 2020 + atomic_set(&mport->state, RIO_DEVICE_INITIALIZING); 2021 + mport->id = next_portid++; 2022 + mport->host_deviceid = rio_get_hdid(mport->id); 2023 + mport->nscan = NULL; 2024 + 2025 + return 0; 2026 + } 2027 + EXPORT_SYMBOL_GPL(rio_mport_initialize); 2028 + 2016 2029 int rio_register_mport(struct rio_mport *port) 2017 2030 { 2018 2031 struct rio_scan_node *scan = NULL; 2019 2032 int res = 0; 2020 2033 2021 - if (next_portid >= RIO_MAX_MPORTS) { 2022 - pr_err("RIO: reached specified max number of mports\n"); 2023 - return 1; 2024 - } 2025 - 2026 - port->id = next_portid++; 2027 - port->host_deviceid = rio_get_hdid(port->id); 2028 - port->nscan = NULL; 2029 - 2030 - dev_set_name(&port->dev, "rapidio%d", port->id); 2031 - port->dev.class = &rio_mport_class; 2032 - 2033 - res = device_register(&port->dev); 2034 - if (res) 2035 - dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n", 2036 - port->id, res); 2037 - else 2038 - dev_dbg(&port->dev, "RIO: mport%d registered\n", port->id); 2039 - 2040 2034 mutex_lock(&rio_mport_list_lock); 2041 - list_add_tail(&port->node, &rio_mports); 2042 2035 2043 2036 /* 2044 2037 * Check if there are any registered enumeration/discovery operations ··· 2048 2049 break; 2049 2050 } 2050 2051 } 2052 + 2053 + list_add_tail(&port->node, &rio_mports); 2051 2054 mutex_unlock(&rio_mport_list_lock); 2052 2055 2053 - pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id); 2054 - return 0; 2056 + dev_set_name(&port->dev, "rapidio%d", port->id); 2057 + port->dev.class = &rio_mport_class; 2058 + atomic_set(&port->state, RIO_DEVICE_RUNNING); 2059 + 2060 + res = device_register(&port->dev); 2061 + if (res) 2062 + dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n", 2063 + port->id, res); 2064 + else 2065 + dev_dbg(&port->dev, "RIO: registered mport%d\n", port->id); 2066 + 2067 + return res; 2055 2068 } 2056 2069 EXPORT_SYMBOL_GPL(rio_register_mport); 2070 + 2071 + static int rio_mport_cleanup_callback(struct device *dev, void *data) 2072 + { 2073 + struct rio_dev *rdev = to_rio_dev(dev); 2074 + 2075 + if (dev->bus == &rio_bus_type) 2076 + rio_del_device(rdev, RIO_DEVICE_SHUTDOWN); 2077 + return 0; 2078 + } 2079 + 2080 + static int rio_net_remove_children(struct rio_net *net) 2081 + { 2082 + /* 2083 + * Unregister all RapidIO devices residing on this net (this will 2084 + * invoke notification of registered subsystem interfaces as well). 2085 + */ 2086 + device_for_each_child(&net->dev, NULL, rio_mport_cleanup_callback); 2087 + return 0; 2088 + } 2089 + 2090 + int rio_unregister_mport(struct rio_mport *port) 2091 + { 2092 + pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id); 2093 + 2094 + /* Transition mport to the SHUTDOWN state */ 2095 + if (atomic_cmpxchg(&port->state, 2096 + RIO_DEVICE_RUNNING, 2097 + RIO_DEVICE_SHUTDOWN) != RIO_DEVICE_RUNNING) { 2098 + pr_err("RIO: %s unexpected state transition for mport %s\n", 2099 + __func__, port->name); 2100 + } 2101 + 2102 + if (port->net && port->net->hport == port) { 2103 + rio_net_remove_children(port->net); 2104 + rio_free_net(port->net); 2105 + } 2106 + 2107 + /* 2108 + * Unregister all RapidIO devices attached to this mport (this will 2109 + * invoke notification of registered subsystem interfaces as well). 2110 + */ 2111 + mutex_lock(&rio_mport_list_lock); 2112 + list_del(&port->node); 2113 + mutex_unlock(&rio_mport_list_lock); 2114 + device_unregister(&port->dev); 2115 + 2116 + return 0; 2117 + } 2118 + EXPORT_SYMBOL_GPL(rio_unregister_mport); 2057 2119 2058 2120 EXPORT_SYMBOL_GPL(rio_local_get_device_id); 2059 2121 EXPORT_SYMBOL_GPL(rio_get_device);
+1 -1
drivers/rapidio/rio.h
··· 43 43 extern int rio_add_net(struct rio_net *net); 44 44 extern void rio_free_net(struct rio_net *net); 45 45 extern int rio_add_device(struct rio_dev *rdev); 46 - extern void rio_del_device(struct rio_dev *rdev); 46 + extern void rio_del_device(struct rio_dev *rdev, enum rio_device_state state); 47 47 extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid, 48 48 u8 hopcount, u8 port_num); 49 49 extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
+18
include/linux/rio.h
··· 137 137 int (*em_handle) (struct rio_dev *dev, u8 swport); 138 138 }; 139 139 140 + enum rio_device_state { 141 + RIO_DEVICE_INITIALIZING, 142 + RIO_DEVICE_RUNNING, 143 + RIO_DEVICE_GONE, 144 + RIO_DEVICE_SHUTDOWN, 145 + }; 146 + 140 147 /** 141 148 * struct rio_dev - RIO device info 142 149 * @global_list: Node in list of all RIO devices ··· 172 165 * @destid: Network destination ID (or associated destid for switch) 173 166 * @hopcount: Hopcount to this device 174 167 * @prev: Previous RIO device connected to the current one 168 + * @state: device state 175 169 * @rswitch: struct rio_switch (if valid for this device) 176 170 */ 177 171 struct rio_dev { ··· 202 194 u16 destid; 203 195 u8 hopcount; 204 196 struct rio_dev *prev; 197 + atomic_t state; 205 198 struct rio_switch rswitch[0]; /* RIO switch info */ 206 199 }; 207 200 ··· 264 255 * @priv: Master port private data 265 256 * @dma: DMA device associated with mport 266 257 * @nscan: RapidIO network enumeration/discovery operations 258 + * @state: mport device state 267 259 */ 268 260 struct rio_mport { 269 261 struct list_head dbells; /* list of doorbell events */ ··· 293 283 struct dma_device dma; 294 284 #endif 295 285 struct rio_scan *nscan; 286 + atomic_t state; 296 287 }; 288 + 289 + static inline int rio_mport_is_running(struct rio_mport *mport) 290 + { 291 + return atomic_read(&mport->state) == RIO_DEVICE_RUNNING; 292 + } 297 293 298 294 /* 299 295 * Enumeration/discovery control flags ··· 541 525 }; 542 526 543 527 /* Architecture and hardware-specific functions */ 528 + extern int rio_mport_initialize(struct rio_mport *); 544 529 extern int rio_register_mport(struct rio_mport *); 530 + extern int rio_unregister_mport(struct rio_mport *); 545 531 extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); 546 532 extern void rio_close_inb_mbox(struct rio_mport *, int); 547 533 extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int);