mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-04 05:37:36 +00:00
rapidio: move net allocation into core code
Make net allocation/release routines available to all components of RapidIO subsystem by moving code from rio-scan enumerator. Make destination ID allocation method private to existing enumerator because other enumeration methods can use their own algorithm. Setup net device object as a parent of all RapidIO devices residing in it and register net as a child of active mport device. 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>
This commit is contained in:
parent
b74ec56e8a
commit
e6b585ca6e
4 changed files with 133 additions and 49 deletions
|
@ -39,6 +39,13 @@
|
||||||
|
|
||||||
static void rio_init_em(struct rio_dev *rdev);
|
static void rio_init_em(struct rio_dev *rdev);
|
||||||
|
|
||||||
|
struct rio_id_table {
|
||||||
|
u16 start; /* logical minimal id */
|
||||||
|
u32 max; /* max number of IDs in table */
|
||||||
|
spinlock_t lock;
|
||||||
|
unsigned long table[0];
|
||||||
|
};
|
||||||
|
|
||||||
static int next_destid = 0;
|
static int next_destid = 0;
|
||||||
static int next_comptag = 1;
|
static int next_comptag = 1;
|
||||||
|
|
||||||
|
@ -62,7 +69,7 @@ static int rio_mport_phys_table[] = {
|
||||||
static u16 rio_destid_alloc(struct rio_net *net)
|
static u16 rio_destid_alloc(struct rio_net *net)
|
||||||
{
|
{
|
||||||
int destid;
|
int destid;
|
||||||
struct rio_id_table *idtab = &net->destid_table;
|
struct rio_id_table *idtab = (struct rio_id_table *)net->enum_data;
|
||||||
|
|
||||||
spin_lock(&idtab->lock);
|
spin_lock(&idtab->lock);
|
||||||
destid = find_first_zero_bit(idtab->table, idtab->max);
|
destid = find_first_zero_bit(idtab->table, idtab->max);
|
||||||
|
@ -88,7 +95,7 @@ static u16 rio_destid_alloc(struct rio_net *net)
|
||||||
static int rio_destid_reserve(struct rio_net *net, u16 destid)
|
static int rio_destid_reserve(struct rio_net *net, u16 destid)
|
||||||
{
|
{
|
||||||
int oldbit;
|
int oldbit;
|
||||||
struct rio_id_table *idtab = &net->destid_table;
|
struct rio_id_table *idtab = (struct rio_id_table *)net->enum_data;
|
||||||
|
|
||||||
destid -= idtab->start;
|
destid -= idtab->start;
|
||||||
spin_lock(&idtab->lock);
|
spin_lock(&idtab->lock);
|
||||||
|
@ -106,7 +113,7 @@ static int rio_destid_reserve(struct rio_net *net, u16 destid)
|
||||||
*/
|
*/
|
||||||
static void rio_destid_free(struct rio_net *net, u16 destid)
|
static void rio_destid_free(struct rio_net *net, u16 destid)
|
||||||
{
|
{
|
||||||
struct rio_id_table *idtab = &net->destid_table;
|
struct rio_id_table *idtab = (struct rio_id_table *)net->enum_data;
|
||||||
|
|
||||||
destid -= idtab->start;
|
destid -= idtab->start;
|
||||||
spin_lock(&idtab->lock);
|
spin_lock(&idtab->lock);
|
||||||
|
@ -121,7 +128,7 @@ static void rio_destid_free(struct rio_net *net, u16 destid)
|
||||||
static u16 rio_destid_first(struct rio_net *net)
|
static u16 rio_destid_first(struct rio_net *net)
|
||||||
{
|
{
|
||||||
int destid;
|
int destid;
|
||||||
struct rio_id_table *idtab = &net->destid_table;
|
struct rio_id_table *idtab = (struct rio_id_table *)net->enum_data;
|
||||||
|
|
||||||
spin_lock(&idtab->lock);
|
spin_lock(&idtab->lock);
|
||||||
destid = find_first_bit(idtab->table, idtab->max);
|
destid = find_first_bit(idtab->table, idtab->max);
|
||||||
|
@ -141,7 +148,7 @@ static u16 rio_destid_first(struct rio_net *net)
|
||||||
static u16 rio_destid_next(struct rio_net *net, u16 from)
|
static u16 rio_destid_next(struct rio_net *net, u16 from)
|
||||||
{
|
{
|
||||||
int destid;
|
int destid;
|
||||||
struct rio_id_table *idtab = &net->destid_table;
|
struct rio_id_table *idtab = (struct rio_id_table *)net->enum_data;
|
||||||
|
|
||||||
spin_lock(&idtab->lock);
|
spin_lock(&idtab->lock);
|
||||||
destid = find_next_bit(idtab->table, idtab->max, from);
|
destid = find_next_bit(idtab->table, idtab->max, from);
|
||||||
|
@ -458,7 +465,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
|
||||||
rdev->comp_tag & RIO_CTAG_UDEVID);
|
rdev->comp_tag & RIO_CTAG_UDEVID);
|
||||||
}
|
}
|
||||||
|
|
||||||
rdev->dev.parent = &port->dev;
|
rdev->dev.parent = &net->dev;
|
||||||
rio_attach_device(rdev);
|
rio_attach_device(rdev);
|
||||||
rdev->dev.release = rio_release_dev;
|
rdev->dev.release = rio_release_dev;
|
||||||
rdev->dma_mask = DMA_BIT_MASK(32);
|
rdev->dma_mask = DMA_BIT_MASK(32);
|
||||||
|
@ -855,50 +862,71 @@ static int rio_mport_is_active(struct rio_mport *port)
|
||||||
return result & RIO_PORT_N_ERR_STS_PORT_OK;
|
return result & RIO_PORT_N_ERR_STS_PORT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void rio_scan_release_net(struct rio_net *net)
|
||||||
* rio_alloc_net- Allocate and configure a new RIO network
|
{
|
||||||
* @port: Master port associated with the RIO network
|
pr_debug("RIO-SCAN: %s: net_%d\n", __func__, net->id);
|
||||||
* @do_enum: Enumeration/Discovery mode flag
|
kfree(net->enum_data);
|
||||||
* @start: logical minimal start id for new net
|
}
|
||||||
*
|
|
||||||
* Allocates a RIO network structure, initializes per-network
|
static void rio_scan_release_dev(struct device *dev)
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static struct rio_net *rio_alloc_net(struct rio_mport *port,
|
|
||||||
int do_enum, u16 start)
|
|
||||||
{
|
{
|
||||||
struct rio_net *net;
|
struct rio_net *net;
|
||||||
|
|
||||||
net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
|
net = to_rio_net(dev);
|
||||||
if (net && do_enum) {
|
pr_debug("RIO-SCAN: %s: net_%d\n", __func__, net->id);
|
||||||
net->destid_table.table = kcalloc(
|
kfree(net);
|
||||||
BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)),
|
}
|
||||||
sizeof(long),
|
|
||||||
GFP_KERNEL);
|
|
||||||
|
|
||||||
if (net->destid_table.table == NULL) {
|
/*
|
||||||
|
* rio_scan_alloc_net - Allocate and configure a new RIO network
|
||||||
|
* @mport: Master port associated with the RIO network
|
||||||
|
* @do_enum: Enumeration/Discovery mode flag
|
||||||
|
* @start: logical minimal start id for new net
|
||||||
|
*
|
||||||
|
* Allocates a new RIO network structure and initializes enumerator-specific
|
||||||
|
* part of it (if required).
|
||||||
|
* Returns a RIO network pointer on success or %NULL on failure.
|
||||||
|
*/
|
||||||
|
static struct rio_net *rio_scan_alloc_net(struct rio_mport *mport,
|
||||||
|
int do_enum, u16 start)
|
||||||
|
{
|
||||||
|
struct rio_net *net;
|
||||||
|
|
||||||
|
net = rio_alloc_net(mport);
|
||||||
|
|
||||||
|
if (net && do_enum) {
|
||||||
|
struct rio_id_table *idtab;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
size = sizeof(struct rio_id_table) +
|
||||||
|
BITS_TO_LONGS(
|
||||||
|
RIO_MAX_ROUTE_ENTRIES(mport->sys_size)
|
||||||
|
) * sizeof(long);
|
||||||
|
|
||||||
|
idtab = kzalloc(size, GFP_KERNEL);
|
||||||
|
|
||||||
|
if (idtab == NULL) {
|
||||||
pr_err("RIO: failed to allocate destID table\n");
|
pr_err("RIO: failed to allocate destID table\n");
|
||||||
kfree(net);
|
rio_free_net(net);
|
||||||
net = NULL;
|
net = NULL;
|
||||||
} else {
|
} else {
|
||||||
net->destid_table.start = start;
|
net->enum_data = idtab;
|
||||||
net->destid_table.max =
|
net->release = rio_scan_release_net;
|
||||||
RIO_MAX_ROUTE_ENTRIES(port->sys_size);
|
idtab->start = start;
|
||||||
spin_lock_init(&net->destid_table.lock);
|
idtab->max = RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
|
||||||
|
spin_lock_init(&idtab->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net) {
|
if (net) {
|
||||||
INIT_LIST_HEAD(&net->node);
|
net->id = mport->id;
|
||||||
INIT_LIST_HEAD(&net->devices);
|
net->hport = mport;
|
||||||
INIT_LIST_HEAD(&net->switches);
|
dev_set_name(&net->dev, "rnet_%d", net->id);
|
||||||
INIT_LIST_HEAD(&net->mports);
|
net->dev.parent = &mport->dev;
|
||||||
list_add_tail(&port->nnode, &net->mports);
|
net->dev.release = rio_scan_release_dev;
|
||||||
net->hport = port;
|
rio_add_net(net);
|
||||||
net->id = port->id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,7 +1035,7 @@ static int rio_enum_mport(struct rio_mport *mport, u32 flags)
|
||||||
|
|
||||||
/* If master port has an active link, allocate net and enum peers */
|
/* If master port has an active link, allocate net and enum peers */
|
||||||
if (rio_mport_is_active(mport)) {
|
if (rio_mport_is_active(mport)) {
|
||||||
net = rio_alloc_net(mport, 1, 0);
|
net = rio_scan_alloc_net(mport, 1, 0);
|
||||||
if (!net) {
|
if (!net) {
|
||||||
printk(KERN_ERR "RIO: failed to allocate new net\n");
|
printk(KERN_ERR "RIO: failed to allocate new net\n");
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
|
@ -1124,7 +1152,7 @@ static int rio_disc_mport(struct rio_mport *mport, u32 flags)
|
||||||
enum_done:
|
enum_done:
|
||||||
pr_debug("RIO: ... enumeration done\n");
|
pr_debug("RIO: ... enumeration done\n");
|
||||||
|
|
||||||
net = rio_alloc_net(mport, 0, 0);
|
net = rio_scan_alloc_net(mport, 0, 0);
|
||||||
if (!net) {
|
if (!net) {
|
||||||
printk(KERN_ERR "RIO: Failed to allocate new net\n");
|
printk(KERN_ERR "RIO: Failed to allocate new net\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
|
@ -42,6 +42,7 @@ MODULE_PARM_DESC(hdid,
|
||||||
"Destination ID assignment to local RapidIO controllers");
|
"Destination ID assignment to local RapidIO controllers");
|
||||||
|
|
||||||
static LIST_HEAD(rio_devices);
|
static LIST_HEAD(rio_devices);
|
||||||
|
static LIST_HEAD(rio_nets);
|
||||||
static DEFINE_SPINLOCK(rio_global_list_lock);
|
static DEFINE_SPINLOCK(rio_global_list_lock);
|
||||||
|
|
||||||
static LIST_HEAD(rio_mports);
|
static LIST_HEAD(rio_mports);
|
||||||
|
@ -84,6 +85,58 @@ int rio_query_mport(struct rio_mport *port,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rio_query_mport);
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rio_free_net);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rio_add_device- Adds a RIO device to the device model
|
* rio_add_device- Adds a RIO device to the device model
|
||||||
* @rdev: RIO device
|
* @rdev: RIO device
|
||||||
|
|
|
@ -39,6 +39,9 @@ extern int rio_route_get_entry(struct rio_dev *rdev, u16 table,
|
||||||
extern int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock);
|
extern int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock);
|
||||||
extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
|
extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
|
||||||
extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
|
extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
|
||||||
|
extern struct rio_net *rio_alloc_net(struct rio_mport *mport);
|
||||||
|
extern int rio_add_net(struct rio_net *net);
|
||||||
|
extern void rio_free_net(struct rio_net *net);
|
||||||
extern int rio_add_device(struct rio_dev *rdev);
|
extern int rio_add_device(struct rio_dev *rdev);
|
||||||
extern void rio_del_device(struct rio_dev *rdev);
|
extern void rio_del_device(struct rio_dev *rdev);
|
||||||
extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
|
extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
|
||||||
|
|
|
@ -202,6 +202,7 @@ struct rio_dev {
|
||||||
#define to_rio_dev(n) container_of(n, struct rio_dev, dev)
|
#define to_rio_dev(n) container_of(n, struct rio_dev, dev)
|
||||||
#define sw_to_rio_dev(n) container_of(n, struct rio_dev, rswitch[0])
|
#define sw_to_rio_dev(n) container_of(n, struct rio_dev, rswitch[0])
|
||||||
#define to_rio_mport(n) container_of(n, struct rio_mport, dev)
|
#define to_rio_mport(n) container_of(n, struct rio_mport, dev)
|
||||||
|
#define to_rio_net(n) container_of(n, struct rio_net, dev)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct rio_msg - RIO message event
|
* struct rio_msg - RIO message event
|
||||||
|
@ -237,6 +238,7 @@ enum rio_phy_type {
|
||||||
* @dbells: List of doorbell events
|
* @dbells: List of doorbell events
|
||||||
* @node: Node in global list of master ports
|
* @node: Node in global list of master ports
|
||||||
* @nnode: Node in network list of master ports
|
* @nnode: Node in network list of master ports
|
||||||
|
* @net: RIO net this mport is attached to
|
||||||
* @iores: I/O mem resource that this master port interface owns
|
* @iores: I/O mem resource that this master port interface owns
|
||||||
* @riores: RIO resources that this master port interfaces owns
|
* @riores: RIO resources that this master port interfaces owns
|
||||||
* @inb_msg: RIO inbound message event descriptors
|
* @inb_msg: RIO inbound message event descriptors
|
||||||
|
@ -258,6 +260,7 @@ struct rio_mport {
|
||||||
struct list_head dbells; /* list of doorbell events */
|
struct list_head dbells; /* list of doorbell events */
|
||||||
struct list_head node; /* node in global list of ports */
|
struct list_head node; /* node in global list of ports */
|
||||||
struct list_head nnode; /* node in net list of ports */
|
struct list_head nnode; /* node in net list of ports */
|
||||||
|
struct rio_net *net; /* RIO net this mport is attached to */
|
||||||
struct resource iores;
|
struct resource iores;
|
||||||
struct resource riores[RIO_MAX_MPORT_RESOURCES];
|
struct resource riores[RIO_MAX_MPORT_RESOURCES];
|
||||||
struct rio_msg inb_msg[RIO_MAX_MBOX];
|
struct rio_msg inb_msg[RIO_MAX_MBOX];
|
||||||
|
@ -287,13 +290,6 @@ struct rio_mport {
|
||||||
*/
|
*/
|
||||||
#define RIO_SCAN_ENUM_NO_WAIT 0x00000001 /* Do not wait for enum completed */
|
#define RIO_SCAN_ENUM_NO_WAIT 0x00000001 /* Do not wait for enum completed */
|
||||||
|
|
||||||
struct rio_id_table {
|
|
||||||
u16 start; /* logical minimal id */
|
|
||||||
u32 max; /* max number of IDs in table */
|
|
||||||
spinlock_t lock;
|
|
||||||
unsigned long *table;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct rio_net - RIO network info
|
* struct rio_net - RIO network info
|
||||||
* @node: Node in global list of RIO networks
|
* @node: Node in global list of RIO networks
|
||||||
|
@ -302,7 +298,9 @@ struct rio_id_table {
|
||||||
* @mports: List of master ports accessing this network
|
* @mports: List of master ports accessing this network
|
||||||
* @hport: Default port for accessing this network
|
* @hport: Default port for accessing this network
|
||||||
* @id: RIO network ID
|
* @id: RIO network ID
|
||||||
* @destid_table: destID allocation table
|
* @dev: Device object
|
||||||
|
* @enum_data: private data specific to a network enumerator
|
||||||
|
* @release: enumerator-specific release callback
|
||||||
*/
|
*/
|
||||||
struct rio_net {
|
struct rio_net {
|
||||||
struct list_head node; /* node in list of networks */
|
struct list_head node; /* node in list of networks */
|
||||||
|
@ -311,7 +309,9 @@ struct rio_net {
|
||||||
struct list_head mports; /* list of ports accessing net */
|
struct list_head mports; /* list of ports accessing net */
|
||||||
struct rio_mport *hport; /* primary port for accessing net */
|
struct rio_mport *hport; /* primary port for accessing net */
|
||||||
unsigned char id; /* RIO network ID */
|
unsigned char id; /* RIO network ID */
|
||||||
struct rio_id_table destid_table; /* destID allocation table */
|
struct device dev;
|
||||||
|
void *enum_data; /* private data for enumerator of the network */
|
||||||
|
void (*release)(struct rio_net *net);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum rio_link_speed {
|
enum rio_link_speed {
|
||||||
|
|
Loading…
Add table
Reference in a new issue