cregit-Linux how code gets into the kernel

Release 4.14 drivers/rapidio/rio.c

Directory: drivers/rapidio
/*
 * RapidIO interconnect services
 * (RapidIO Interconnect Specification, http://www.rapidio.org)
 *
 * Copyright 2005 MontaVista Software, Inc.
 * Matt Porter <mporter@kernel.crashing.org>
 *
 * Copyright 2009 - 2013 Integrated Device Technology, Inc.
 * Alex Bounine <alexandre.bounine@idt.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#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 {
	
struct list_head node;

	
int (*pwcback)(struct rio_mport *mport, void *context,
		       union rio_pw_msg *msg, int step);
	
void *context;
};

MODULE_DESCRIPTION("RapidIO Subsystem Core");
MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
MODULE_AUTHOR("Alexandre Bounine <alexandre.bounine@idt.com>");
MODULE_LICENSE("GPL");


static int hdid[RIO_MAX_MPORTS];

static int ids_num;
module_param_array(hdid, int, &ids_num, 0);
MODULE_PARM_DESC(hdid,
	"Destination ID assignment to local RapidIO controllers");

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) { u32 result; rio_local_read_config_32(port, RIO_DID_CSR, &result); return (RIO_GET_DID(port->sys_size, result)); }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter3188.57%150.00%
Zhang Wei411.43%150.00%
Total35100.00%2100.00%

/** * 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) { if (!port->ops->query_mport) return -ENODATA; return port->ops->query_mport(port, mport_attr); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine40100.00%1100.00%
Total40100.00%1100.00%

EXPORT_SYMBOL(rio_query_mport); /** * 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) { struct rio_net *net; net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); if (net) { INIT_LIST_HEAD(&net->node); INIT_LIST_HEAD(&net->devices); INIT_LIST_HEAD(&net->switches); INIT_LIST_HEAD(&net->mports); mport->net = net; } return net; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine77100.00%1100.00%
Total77100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_alloc_net);
int rio_add_net(struct rio_net *net) { int err; err = device_register(&net->dev); if (err) return err; spin_lock(&rio_global_list_lock); list_add_tail(&net->node, &rio_nets); spin_unlock(&rio_global_list_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine56100.00%1100.00%
Total56100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_add_net);
void rio_free_net(struct rio_net *net) { spin_lock(&rio_global_list_lock); if (!list_empty(&net->node)) list_del(&net->node); spin_unlock(&rio_global_list_lock); if (net->release) net->release(net); device_unregister(&net->dev); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine62100.00%1100.00%
Total62100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_free_net); /** * 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) { rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size, did)); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine29100.00%1100.00%
Total29100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_local_set_device_id); /** * 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) { int err; atomic_set(&rdev->state, RIO_DEVICE_RUNNING); err = device_register(&rdev->dev); if (err) return err; spin_lock(&rio_global_list_lock); list_add_tail(&rdev->global_list, &rio_devices); if (rdev->net) { list_add_tail(&rdev->net_list, &rdev->net->devices); if (rdev->pef & RIO_PEF_SWITCH) list_add_tail(&rdev->rswitch->node, &rdev->net->switches); } spin_unlock(&rio_global_list_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine114100.00%3100.00%
Total114100.00%3100.00%

EXPORT_SYMBOL_GPL(rio_add_device); /* * 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) { pr_debug("RIO: %s: removing %s\n", __func__, rio_name(rdev)); atomic_set(&rdev->state, state); spin_lock(&rio_global_list_lock); list_del(&rdev->global_list); if (rdev->net) { list_del(&rdev->net_list); if (rdev->pef & RIO_PEF_SWITCH) { list_del(&rdev->rswitch->node); kfree(rdev->rswitch->route_table); } } spin_unlock(&rio_global_list_lock); device_unregister(&rdev->dev); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine109100.00%2100.00%
Total109100.00%2100.00%

EXPORT_SYMBOL_GPL(rio_del_device); /** * 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)) { int rc = -ENOSYS; struct resource *res; if (mport->ops->open_inb_mbox == NULL) goto out; res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); /* Make sure this mailbox isn't in use */ if ((rc = request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE], res)) < 0) { kfree(res); goto out; } mport->inb_msg[mbox].res = res; /* Hook the inbound message callback */ mport->inb_msg[mbox].mcback = minb; rc = mport->ops->open_inb_mbox(mport, dev_id, mbox, entries); if (rc) { mport->inb_msg[mbox].mcback = NULL; mport->inb_msg[mbox].res = NULL; release_resource(res); kfree(res); } } else rc = -ENOMEM; out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter15270.70%240.00%
Alexandre Bounine6228.84%240.00%
Toshi Kani10.47%120.00%
Total215100.00%5100.00%

/** * 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) { int rc; if (!mport->ops->close_inb_mbox || !mport->inb_msg[mbox].res) return -EINVAL; mport->ops->close_inb_mbox(mport, mbox); mport->inb_msg[mbox].mcback = NULL; rc = release_resource(mport->inb_msg[mbox].res); if (rc) return rc; kfree(mport->inb_msg[mbox].res); mport->inb_msg[mbox].res = NULL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine7872.22%266.67%
Matt Porter3027.78%133.33%
Total108100.00%3100.00%

/** * 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)) { int rc = -ENOSYS; struct resource *res; if (mport->ops->open_outb_mbox == NULL) goto out; res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); /* Make sure this outbound mailbox isn't in use */ if ((rc = request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE], res)) < 0) { kfree(res); goto out; } mport->outb_msg[mbox].res = res; /* Hook the inbound message callback */ mport->outb_msg[mbox].mcback = moutb; rc = mport->ops->open_outb_mbox(mport, dev_id, mbox, entries); if (rc) { mport->outb_msg[mbox].mcback = NULL; mport->outb_msg[mbox].res = NULL; release_resource(res); kfree(res); } } else rc = -ENOMEM; out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter15270.70%240.00%
Alexandre Bounine6228.84%240.00%
Toshi Kani10.47%120.00%
Total215100.00%5100.00%

/** * 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) { int rc; if (!mport->ops->close_outb_mbox || !mport->outb_msg[mbox].res) return -EINVAL; mport->ops->close_outb_mbox(mport, mbox); mport->outb_msg[mbox].mcback = NULL; rc = release_resource(mport->outb_msg[mbox].res); if (rc) return rc; kfree(mport->outb_msg[mbox].res); mport->outb_msg[mbox].res = NULL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine7872.22%266.67%
Matt Porter3027.78%133.33%
Total108100.00%3100.00%

/** * 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)) { int rc = 0; struct rio_dbell *dbell; if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) { rc = -ENOMEM; goto out; } dbell->res = res; dbell->dinb = dinb; dbell->dev_id = dev_id; mutex_lock(&mport->lock); list_add_tail(&dbell->node, &mport->dbells); mutex_unlock(&mport->lock); out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter11988.15%266.67%
Alexandre Bounine1611.85%133.33%
Total135100.00%3100.00%

/** * 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)) { int rc = 0; struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); /* Make sure these doorbells aren't in use */ if ((rc = request_resource(&mport->riores[RIO_DOORBELL_RESOURCE], res)) < 0) { kfree(res); goto out; } /* Hook the doorbell callback */ rc = rio_setup_inb_dbell(mport, dev_id, res, dinb); } else rc = -ENOMEM; out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter13799.28%266.67%
Toshi Kani10.72%133.33%
Total138100.00%3100.00%

/** * 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) { int rc = 0, found = 0; struct rio_dbell *dbell; mutex_lock(&mport->lock); list_for_each_entry(dbell, &mport->dbells, node) { if ((dbell->res->start == start) && (dbell->res->end == end)) { list_del(&dbell->node); found = 1; break; } } mutex_unlock(&mport->lock); /* If we can't find an exact match, fail */ if (!found) { rc = -EINVAL; goto out; } /* Release the doorbell resource */ rc = release_resource(dbell->res); /* Free the doorbell event */ kfree(dbell); out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter10681.54%150.00%
Alexandre Bounine2418.46%150.00%
Total130100.00%2100.00%

/** * 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) { struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); /* Make sure these doorbells aren't in use */ if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res) < 0) { kfree(res); res = NULL; } } return res; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter8098.77%150.00%
Toshi Kani11.23%150.00%
Total81100.00%2100.00%

/** * 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) { int rc = release_resource(res); kfree(res); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Matt Porter31100.00%1100.00%
Total31100.00%1100.00%

/** * 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)) { int rc = 0; struct rio_pwrite *pwrite; pwrite = kzalloc(sizeof(struct rio_pwrite), GFP_KERNEL); if (!pwrite) { rc = -ENOMEM; goto out; } pwrite->pwcback = pwcback; pwrite->context = context; mutex_lock(&mport->lock); list_add_tail(&pwrite->node, &mport->pwrites); mutex_unlock(&mport->lock); out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine122100.00%1100.00%
Total122100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler); /** * 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)) { int rc = -EINVAL; struct rio_pwrite *pwrite; mutex_lock(&mport->lock); list_for_each_entry(pwrite, &mport->pwrites, node) { if (pwrite->pwcback == pwcback && pwrite->context == context) { list_del(&pwrite->node); kfree(pwrite); rc = 0; break; } } mutex_unlock(&mport->lock); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine112100.00%1100.00%
Total112100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_del_mport_pw_handler); /** * 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)) { int rc = 0; spin_lock(&rio_global_list_lock); if (rdev->pwcback != NULL) rc = -ENOMEM; else rdev->pwcback = pwcback; spin_unlock(&rio_global_list_lock); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine70100.00%1100.00%
Total70100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_request_inb_pwrite); /** * 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) { int rc = -ENOMEM; spin_lock(&rio_global_list_lock); if (rdev->pwcback) { rdev->pwcback = NULL; rc = 0; } spin_unlock(&rio_global_list_lock); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine49100.00%1100.00%
Total49100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); /** * 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) { if (mport->ops->pwenable) { mutex_lock(&mport->lock); if ((enable && ++mport->pwe_refcnt == 1) || (!enable && mport->pwe_refcnt && --mport->pwe_refcnt == 0)) mport->ops->pwenable(mport, enable); mutex_unlock(&mport->lock); } }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine79100.00%1100.00%
Total79100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_pw_enable); /** * 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) { int rc = 0; unsigned long flags; if (!mport->ops->map_inb) return -1; spin_lock_irqsave(&rio_mmap_lock, flags); rc = mport->ops->map_inb(mport, local, rbase, size, rflags); spin_unlock_irqrestore(&rio_mmap_lock, flags); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine82100.00%1100.00%
Total82100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_map_inb_region); /** * 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) { unsigned long flags; if (!mport->ops->unmap_inb) return; spin_lock_irqsave(&rio_mmap_lock, flags); mport->ops->unmap_inb(mport, lstart); spin_unlock_irqrestore(&rio_mmap_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine54100.00%1100.00%
Total54100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_unmap_inb_region); /** * 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) { int rc = 0; unsigned long flags; if (!mport->ops->map_outb) return -ENODEV; spin_lock_irqsave(&rio_mmap_lock, flags); rc = mport->ops->map_outb(mport, destid, rbase, size, rflags, local); spin_unlock_irqrestore(&rio_mmap_lock, flags); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine88100.00%1100.00%
Total88100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_map_outb_region); /** * rio_unmap_inb_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) { unsigned long flags; if (!mport->ops->unmap_outb) return; spin_lock_irqsave(&rio_mmap_lock, flags); mport->ops->unmap_outb(mport, destid, rstart); spin_unlock_irqrestore(&rio_mmap_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine59100.00%1100.00%
Total59100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_unmap_outb_region); /** * 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) { u32 ext_ftr_ptr; u32 ftr_header; ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0); while (ext_ftr_ptr) { if (local) rio_local_read_config_32(port, ext_ftr_ptr, &ftr_header); else rio_mport_read_config_32(port, destid, hopcount, ext_ftr_ptr, &ftr_header); ftr_header = RIO_GET_BLOCK_ID(ftr_header); switch (ftr_header) { case RIO_EFB_SER_EP_ID: case RIO_EFB_SER_EP_REC_ID: case RIO_EFB_SER_EP_FREE_ID: case RIO_EFB_SER_EP_M1_ID: case RIO_EFB_SER_EP_SW_M1_ID: case RIO_EFB_SER_EPF_M1_ID: case RIO_EFB_SER_EPF_SW_M1_ID: *rmap = 1; return ext_ftr_ptr; case RIO_EFB_SER_EP_M2_ID: case RIO_EFB_SER_EP_SW_M2_ID: case RIO_EFB_SER_EPF_M2_ID: case RIO_EFB_SER_EPF_SW_M2_ID: *rmap = 2; return ext_ftr_ptr; default: break; } ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, ext_ftr_ptr); } return ext_ftr_ptr; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine161100.00%2100.00%
Total161100.00%2100.00%

EXPORT_SYMBOL_GPL(rio_mport_get_physefb); /** * 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) { struct list_head *n; struct rio_dev *rdev; spin_lock(&rio_global_list_lock); n = from ? from->global_list.next : rio_devices.next; while (n && (n != &rio_devices)) { rdev = rio_dev_g(n); if (rdev->comp_tag == comp_tag) goto exit; n = n->next; } rdev = NULL; exit: spin_unlock(&rio_global_list_lock); return rdev; }

Contributors

PersonTokensPropCommitsCommitProp
Alexandre Bounine97100.00%1100.00%
Total97100.00%1100.00%

EXPORT_SYMBOL_GPL(rio_get_comptag); /** * 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) { u32 regval; rio_read_config_32(rdev, RIO_DEV_PORT_N_CTL_CSR(rdev, pnum), &regval); if (lock) regval |= RIO_PORT_N_CTL_LOCKOUT; else regval &= ~