// SPDX-License-Identifier: GPL-2.0-or-later /* * RapidIO interconnect services * (RapidIO Interconnect Specification, http://www.rapidio.org) * * Copyright 2005 MontaVista Software, Inc. * Matt Porter <[email protected]> * * Copyright 2009 - 2013 Integrated Device Technology, Inc. * Alex Bounine <[email protected]> */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/rio.h> #include <linux/rio_drv.h> #include <linux/rio_ids.h> #include <linux/rio_regs.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/interrupt.h> #include "rio.h" /* * struct rio_pwrite - RIO portwrite event * @node: Node in list of doorbell events * @pwcback: Doorbell event callback * @context: Handler specific context to pass on event */ struct rio_pwrite { … }; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; static int hdid[RIO_MAX_MPORTS]; static int ids_num; module_param_array(…); MODULE_PARM_DESC(…) …; static LIST_HEAD(rio_devices); static LIST_HEAD(rio_nets); static DEFINE_SPINLOCK(rio_global_list_lock); static LIST_HEAD(rio_mports); static LIST_HEAD(rio_scans); static DEFINE_MUTEX(rio_mport_list_lock); static unsigned char next_portid; static DEFINE_SPINLOCK(rio_mmap_lock); /** * rio_local_get_device_id - Get the base/extended device id for a port * @port: RIO master port from which to get the deviceid * * Reads the base/extended device id from the local device * implementing the master port. Returns the 8/16-bit device * id. */ u16 rio_local_get_device_id(struct rio_mport *port) { … } EXPORT_SYMBOL_GPL(…); /** * rio_query_mport - Query mport device attributes * @port: mport device to query * @mport_attr: mport attributes data structure * * Returns attributes of specified mport through the * pointer to attributes data structure. */ int rio_query_mport(struct rio_mport *port, struct rio_mport_attr *mport_attr) { … } EXPORT_SYMBOL(…); /** * rio_alloc_net- Allocate and initialize a new RIO network data structure * @mport: Master port associated with the RIO network * * Allocates a RIO network structure, initializes per-network * list heads, and adds the associated master port to the * network list of associated master ports. Returns a * RIO network pointer on success or %NULL on failure. */ struct rio_net *rio_alloc_net(struct rio_mport *mport) { … } EXPORT_SYMBOL_GPL(…); int rio_add_net(struct rio_net *net) { … } EXPORT_SYMBOL_GPL(…); void rio_free_net(struct rio_net *net) { … } EXPORT_SYMBOL_GPL(…); /** * rio_local_set_device_id - Set the base/extended device id for a port * @port: RIO master port * @did: Device ID value to be written * * Writes the base/extended device id from a device. */ void rio_local_set_device_id(struct rio_mport *port, u16 did) { … } EXPORT_SYMBOL_GPL(…); /** * rio_add_device- Adds a RIO device to the device model * @rdev: RIO device * * Adds the RIO device to the global device list and adds the RIO * device to the RIO device list. Creates the generic sysfs nodes * for an RIO device. */ int rio_add_device(struct rio_dev *rdev) { … } EXPORT_SYMBOL_GPL(…); /* * rio_del_device - removes a RIO device from the device model * @rdev: RIO device * @state: device state to set during removal process * * Removes the RIO device to the kernel device list and subsystem's device list. * Clears sysfs entries for the removed device. */ void rio_del_device(struct rio_dev *rdev, enum rio_device_state state) { … } EXPORT_SYMBOL_GPL(…); /** * rio_request_inb_mbox - request inbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in inbound mailbox queue * @minb: Callback to execute when inbound message is received * * Requests ownership of an inbound mailbox resource and binds * a callback function to the resource. Returns %0 on success. */ int rio_request_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries, void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_inb_mbox - release inbound mailbox message service * @mport: RIO master port from which to release the mailbox resource * @mbox: Mailbox number to release * * Releases ownership of an inbound mailbox resource. Returns 0 * if the request has been satisfied. */ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) { … } EXPORT_SYMBOL_GPL(…); /** * rio_request_outb_mbox - request outbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in outbound mailbox queue * @moutb: Callback to execute when outbound message is sent * * Requests ownership of an outbound mailbox resource and binds * a callback function to the resource. Returns 0 on success. */ int rio_request_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries, void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_outb_mbox - release outbound mailbox message service * @mport: RIO master port from which to release the mailbox resource * @mbox: Mailbox number to release * * Releases ownership of an inbound mailbox resource. Returns 0 * if the request has been satisfied. */ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) { … } EXPORT_SYMBOL_GPL(…); /** * rio_setup_inb_dbell - bind inbound doorbell callback * @mport: RIO master port to bind the doorbell callback * @dev_id: Device specific pointer to pass on event * @res: Doorbell message resource * @dinb: Callback to execute when doorbell is received * * Adds a doorbell resource/callback pair into a port's * doorbell event list. Returns 0 if the request has been * satisfied. */ static int rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res, void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { … } /** * rio_request_inb_dbell - request inbound doorbell message service * @mport: RIO master port from which to allocate the doorbell resource * @dev_id: Device specific pointer to pass on event * @start: Doorbell info range start * @end: Doorbell info range end * @dinb: Callback to execute when doorbell is received * * Requests ownership of an inbound doorbell resource and binds * a callback function to the resource. Returns 0 if the request * has been satisfied. */ int rio_request_inb_dbell(struct rio_mport *mport, void *dev_id, u16 start, u16 end, void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_inb_dbell - release inbound doorbell message service * @mport: RIO master port from which to release the doorbell resource * @start: Doorbell info range start * @end: Doorbell info range end * * Releases ownership of an inbound doorbell resource and removes * callback from the doorbell event list. Returns 0 if the request * has been satisfied. */ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) { … } EXPORT_SYMBOL_GPL(…); /** * rio_request_outb_dbell - request outbound doorbell message range * @rdev: RIO device from which to allocate the doorbell resource * @start: Doorbell message range start * @end: Doorbell message range end * * Requests ownership of a doorbell message range. Returns a resource * if the request has been satisfied or %NULL on failure. */ struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, u16 end) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_outb_dbell - release outbound doorbell message range * @rdev: RIO device from which to release the doorbell resource * @res: Doorbell resource to be freed * * Releases ownership of a doorbell message range. Returns 0 if the * request has been satisfied. */ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) { … } EXPORT_SYMBOL_GPL(…); /** * rio_add_mport_pw_handler - add port-write message handler into the list * of mport specific pw handlers * @mport: RIO master port to bind the portwrite callback * @context: Handler specific context to pass on event * @pwcback: Callback to execute when portwrite is received * * Returns 0 if the request has been satisfied. */ int rio_add_mport_pw_handler(struct rio_mport *mport, void *context, int (*pwcback)(struct rio_mport *mport, void *context, union rio_pw_msg *msg, int step)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_del_mport_pw_handler - remove port-write message handler from the list * of mport specific pw handlers * @mport: RIO master port to bind the portwrite callback * @context: Registered handler specific context to pass on event * @pwcback: Registered callback function * * Returns 0 if the request has been satisfied. */ int rio_del_mport_pw_handler(struct rio_mport *mport, void *context, int (*pwcback)(struct rio_mport *mport, void *context, union rio_pw_msg *msg, int step)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_request_inb_pwrite - request inbound port-write message service for * specific RapidIO device * @rdev: RIO device to which register inbound port-write callback routine * @pwcback: Callback routine to execute when port-write is received * * Binds a port-write callback function to the RapidIO device. * Returns 0 if the request has been satisfied. */ int rio_request_inb_pwrite(struct rio_dev *rdev, int (*pwcback)(struct rio_dev *rdev, union rio_pw_msg *msg, int step)) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_inb_pwrite - release inbound port-write message service * associated with specific RapidIO device * @rdev: RIO device which registered for inbound port-write callback * * Removes callback from the rio_dev structure. Returns 0 if the request * has been satisfied. */ int rio_release_inb_pwrite(struct rio_dev *rdev) { … } EXPORT_SYMBOL_GPL(…); /** * rio_pw_enable - Enables/disables port-write handling by a master port * @mport: Master port associated with port-write handling * @enable: 1=enable, 0=disable */ void rio_pw_enable(struct rio_mport *mport, int enable) { … } EXPORT_SYMBOL_GPL(…); /** * rio_map_inb_region -- Map inbound memory region. * @mport: Master port. * @local: physical address of memory region to be mapped * @rbase: RIO base address assigned to this window * @size: Size of the memory region * @rflags: Flags for mapping. * * Return: 0 -- Success. * * This function will create the mapping from RIO space to local memory. */ int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, u64 rbase, u32 size, u32 rflags) { … } EXPORT_SYMBOL_GPL(…); /** * rio_unmap_inb_region -- Unmap the inbound memory region * @mport: Master port * @lstart: physical address of memory region to be unmapped */ void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart) { … } EXPORT_SYMBOL_GPL(…); /** * rio_map_outb_region -- Map outbound memory region. * @mport: Master port. * @destid: destination id window points to * @rbase: RIO base address window translates to * @size: Size of the memory region * @rflags: Flags for mapping. * @local: physical address of memory region mapped * * Return: 0 -- Success. * * This function will create the mapping from RIO space to local memory. */ int rio_map_outb_region(struct rio_mport *mport, u16 destid, u64 rbase, u32 size, u32 rflags, dma_addr_t *local) { … } EXPORT_SYMBOL_GPL(…); /** * rio_unmap_outb_region -- Unmap the inbound memory region * @mport: Master port * @destid: destination id mapping points to * @rstart: RIO base address window translates to */ void rio_unmap_outb_region(struct rio_mport *mport, u16 destid, u64 rstart) { … } EXPORT_SYMBOL_GPL(…); /** * rio_mport_get_physefb - Helper function that returns register offset * for Physical Layer Extended Features Block. * @port: Master port to issue transaction * @local: Indicate a local master port or remote device access * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @rmap: pointer to location to store register map type info */ u32 rio_mport_get_physefb(struct rio_mport *port, int local, u16 destid, u8 hopcount, u32 *rmap) { … } EXPORT_SYMBOL_GPL(…); /** * rio_get_comptag - Begin or continue searching for a RIO device by component tag * @comp_tag: RIO component tag to match * @from: Previous RIO device found in search, or %NULL for new search * * Iterates through the list of known RIO devices. If a RIO device is * found with a matching @comp_tag, a pointer to its device * structure is returned. Otherwise, %NULL is returned. A new search * is initiated by passing %NULL to the @from argument. Otherwise, if * @from is not %NULL, searches continue from next device on the global * list. */ struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) { … } EXPORT_SYMBOL_GPL(…); /** * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port. * @rdev: Pointer to RIO device control structure * @pnum: Switch port number to set LOCKOUT bit * @lock: Operation : set (=1) or clear (=0) */ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) { … } EXPORT_SYMBOL_GPL(…); /** * rio_enable_rx_tx_port - enable input receiver and output transmitter of * given port * @port: Master port associated with the RIO network * @local: local=1 select local port otherwise a far device is reached * @destid: Destination ID of the device to check host bit * @hopcount: Number of hops to reach the target * @port_num: Port (-number on switch) to enable on a far end device * * Returns 0 or 1 from on General Control Command and Status Register * (EXT_PTR+0x3C) */ int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid, u8 hopcount, u8 port_num) { … } EXPORT_SYMBOL_GPL(…); /** * rio_chk_dev_route - Validate route to the specified device. * @rdev: RIO device failed to respond * @nrdev: Last active device on the route to rdev * @npnum: nrdev's port number on the route to rdev * * Follows a route to the specified RIO device to determine the last available * device (and corresponding RIO port) on the route. */ static int rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) { … } /** * rio_mport_chk_dev_access - Validate access to the specified device. * @mport: Master port to send transactions * @destid: Device destination ID in network * @hopcount: Number of hops into the network */ int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) { … } EXPORT_SYMBOL_GPL(…); /** * rio_chk_dev_access - Validate access to the specified device. * @rdev: Pointer to RIO device control structure */ static int rio_chk_dev_access(struct rio_dev *rdev) { … } /** * rio_get_input_status - Sends a Link-Request/Input-Status control symbol and * returns link-response (if requested). * @rdev: RIO devive to issue Input-status command * @pnum: Device port number to issue the command * @lnkresp: Response from a link partner */ static int rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) { … } /** * rio_clr_err_stopped - Clears port Error-stopped states. * @rdev: Pointer to RIO device control structure * @pnum: Switch port number to clear errors * @err_status: port error status (if 0 reads register from device) * * TODO: Currently this routine is not compatible with recovery process * specified for idt_gen3 RapidIO switch devices. It has to be reviewed * to implement universal recovery process that is compatible full range * off available devices. * IDT gen3 switch driver now implements HW-specific error handler that * issues soft port reset to the port to reset ERR_STOP bits and ackIDs. */ static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) { … } /** * rio_inb_pwrite_handler - inbound port-write message handler * @mport: mport device associated with port-write * @pw_msg: pointer to inbound port-write message * * Processes an inbound port-write message. Returns 0 if the request * has been satisfied. */ int rio_inb_pwrite_handler(struct rio_mport *mport, union rio_pw_msg *pw_msg) { … } EXPORT_SYMBOL_GPL(…); /** * rio_mport_get_efb - get pointer to next extended features block * @port: Master port to issue transaction * @local: Indicate a local master port or remote device access * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @from: Offset of current Extended Feature block header (if 0 starts * from ExtFeaturePtr) */ u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, u8 hopcount, u32 from) { … } EXPORT_SYMBOL_GPL(…); /** * rio_mport_get_feature - query for devices' extended features * @port: Master port to issue transaction * @local: Indicate a local master port or remote device access * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @ftr: Extended feature code * * Tell if a device supports a given RapidIO capability. * Returns the offset of the requested extended feature * block within the device's RIO configuration space or * 0 in case the device does not support it. */ u32 rio_mport_get_feature(struct rio_mport * port, int local, u16 destid, u8 hopcount, int ftr) { … } EXPORT_SYMBOL_GPL(…); /** * rio_std_route_add_entry - Add switch route table entry using standard * registers defined in RIO specification rev.1.3 * @mport: Master port to issue transaction * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @table: routing table ID (global or port-specific) * @route_destid: destID entry in the RT * @route_port: destination port for specified destID */ static int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 route_port) { … } /** * rio_std_route_get_entry - Read switch route table entry (port number) * associated with specified destID using standard registers defined in RIO * specification rev.1.3 * @mport: Master port to issue transaction * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @table: routing table ID (global or port-specific) * @route_destid: destID entry in the RT * @route_port: returned destination port for specified destID */ static int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 *route_port) { … } /** * rio_std_route_clr_table - Clear swotch route table using standard registers * defined in RIO specification rev.1.3. * @mport: Master port to issue transaction * @destid: Destination ID of the device * @hopcount: Number of switch hops to the device * @table: routing table ID (global or port-specific) */ static int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table) { … } /** * rio_lock_device - Acquires host device lock for specified device * @port: Master port to send transaction * @destid: Destination ID for device/switch * @hopcount: Hopcount to reach switch * @wait_ms: Max wait time in msec (0 = no timeout) * * Attepts to acquire host device lock for specified device * Returns 0 if device lock acquired or EINVAL if timeout expires. */ int rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms) { … } EXPORT_SYMBOL_GPL(…); /** * rio_unlock_device - Releases host device lock for specified device * @port: Master port to send transaction * @destid: Destination ID for device/switch * @hopcount: Hopcount to reach switch * * Returns 0 if device lock released or EINVAL if fails. */ int rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) { … } EXPORT_SYMBOL_GPL(…); /** * rio_route_add_entry- Add a route entry to a switch routing table * @rdev: RIO device * @table: Routing table ID * @route_destid: Destination ID to be routed * @route_port: Port number to be routed * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) * * If available calls the switch specific add_entry() method to add a route * entry into a switch routing table. Otherwise uses standard RT update method * as defined by RapidIO specification. A specific routing table can be selected * using the @table argument if a switch has per port routing tables or * the standard (or global) table may be used by passing * %RIO_GLOBAL_TABLE in @table. * * Returns %0 on success or %-EINVAL on failure. */ int rio_route_add_entry(struct rio_dev *rdev, u16 table, u16 route_destid, u8 route_port, int lock) { … } EXPORT_SYMBOL_GPL(…); /** * rio_route_get_entry- Read an entry from a switch routing table * @rdev: RIO device * @table: Routing table ID * @route_destid: Destination ID to be routed * @route_port: Pointer to read port number into * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) * * If available calls the switch specific get_entry() method to fetch a route * entry from a switch routing table. Otherwise uses standard RT read method * as defined by RapidIO specification. A specific routing table can be selected * using the @table argument if a switch has per port routing tables or * the standard (or global) table may be used by passing * %RIO_GLOBAL_TABLE in @table. * * Returns %0 on success or %-EINVAL on failure. */ int rio_route_get_entry(struct rio_dev *rdev, u16 table, u16 route_destid, u8 *route_port, int lock) { … } EXPORT_SYMBOL_GPL(…); /** * rio_route_clr_table - Clear a switch routing table * @rdev: RIO device * @table: Routing table ID * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) * * If available calls the switch specific clr_table() method to clear a switch * routing table. Otherwise uses standard RT write method as defined by RapidIO * specification. A specific routing table can be selected using the @table * argument if a switch has per port routing tables or the standard (or global) * table may be used by passing %RIO_GLOBAL_TABLE in @table. * * Returns %0 on success or %-EINVAL on failure. */ int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock) { … } EXPORT_SYMBOL_GPL(…); #ifdef CONFIG_RAPIDIO_DMA_ENGINE static bool rio_chan_filter(struct dma_chan *chan, void *arg) { … } /** * rio_request_mport_dma - request RapidIO capable DMA channel associated * with specified local RapidIO mport device. * @mport: RIO mport to perform DMA data transfers * * Returns pointer to allocated DMA channel or NULL if failed. */ struct dma_chan *rio_request_mport_dma(struct rio_mport *mport) { … } EXPORT_SYMBOL_GPL(…); /** * rio_request_dma - request RapidIO capable DMA channel that supports * specified target RapidIO device. * @rdev: RIO device associated with DMA transfer * * Returns pointer to allocated DMA channel or NULL if failed. */ struct dma_chan *rio_request_dma(struct rio_dev *rdev) { … } EXPORT_SYMBOL_GPL(…); /** * rio_release_dma - release specified DMA channel * @dchan: DMA channel to release */ void rio_release_dma(struct dma_chan *dchan) { … } EXPORT_SYMBOL_GPL(…); /** * rio_dma_prep_xfer - RapidIO specific wrapper * for device_prep_slave_sg callback defined by DMAENGINE. * @dchan: DMA channel to configure * @destid: target RapidIO device destination ID * @data: RIO specific data descriptor * @direction: DMA data transfer direction (TO or FROM the device) * @flags: dmaengine defined flags * * Initializes RapidIO capable DMA channel for the specified data transfer. * Uses DMA channel private extension to pass information related to remote * target RIO device. * * Returns: pointer to DMA transaction descriptor if successful, * error-valued pointer or NULL if failed. */ struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan, u16 destid, struct rio_dma_data *data, enum dma_transfer_direction direction, unsigned long flags) { … } EXPORT_SYMBOL_GPL(…); /** * rio_dma_prep_slave_sg - RapidIO specific wrapper * for device_prep_slave_sg callback defined by DMAENGINE. * @rdev: RIO device control structure * @dchan: DMA channel to configure * @data: RIO specific data descriptor * @direction: DMA data transfer direction (TO or FROM the device) * @flags: dmaengine defined flags * * Initializes RapidIO capable DMA channel for the specified data transfer. * Uses DMA channel private extension to pass information related to remote * target RIO device. * * Returns: pointer to DMA transaction descriptor if successful, * error-valued pointer or NULL if failed. */ struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, struct dma_chan *dchan, struct rio_dma_data *data, enum dma_transfer_direction direction, unsigned long flags) { … } EXPORT_SYMBOL_GPL(…); #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ /** * rio_find_mport - find RIO mport by its ID * @mport_id: number (ID) of mport device * * Given a RIO mport number, the desired mport is located * in the global list of mports. If the mport is found, a pointer to its * data structure is returned. If no mport is found, %NULL is returned. */ struct rio_mport *rio_find_mport(int mport_id) { … } /** * rio_register_scan - enumeration/discovery method registration interface * @mport_id: mport device ID for which fabric scan routine has to be set * (RIO_MPORT_ANY = set for all available mports) * @scan_ops: enumeration/discovery operations structure * * Registers enumeration/discovery operations with RapidIO subsystem and * attaches it to the specified mport device (or all available mports * if RIO_MPORT_ANY is specified). * * Returns error if the mport already has an enumerator attached to it. * In case of RIO_MPORT_ANY skips mports with valid scan routines (no error). */ int rio_register_scan(int mport_id, struct rio_scan *scan_ops) { … } EXPORT_SYMBOL_GPL(…); /** * rio_unregister_scan - removes enumeration/discovery method from mport * @mport_id: mport device ID for which fabric scan routine has to be * unregistered (RIO_MPORT_ANY = apply to all mports that use * the specified scan_ops) * @scan_ops: enumeration/discovery operations structure * * Removes enumeration or discovery method assigned to the specified mport * device. If RIO_MPORT_ANY is specified, removes the specified operations from * all mports that have them attached. */ int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops) { … } EXPORT_SYMBOL_GPL(…); /** * rio_mport_scan - execute enumeration/discovery on the specified mport * @mport_id: number (ID) of mport device */ int rio_mport_scan(int mport_id) { … } static struct workqueue_struct *rio_wq; struct rio_disc_work { … }; static void disc_work_handler(struct work_struct *_work) { … } int rio_init_mports(void) { … } EXPORT_SYMBOL_GPL(…); static int rio_get_hdid(int index) { … } int rio_mport_initialize(struct rio_mport *mport) { … } EXPORT_SYMBOL_GPL(…); int rio_register_mport(struct rio_mport *port) { … } EXPORT_SYMBOL_GPL(…); static int rio_mport_cleanup_callback(struct device *dev, void *data) { … } static int rio_net_remove_children(struct rio_net *net) { … } int rio_unregister_mport(struct rio_mport *port) { … } EXPORT_SYMBOL_GPL(…);