[RAPIDIO] Auto-probe the RapidIO system size
The RapidIO system size will auto probe in RIO setup. The route table and rionet_active in rionet.c are changed to be allocated dynamically according to the size of the system. Signed-off-by: Zhang Wei <wei.zhang@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Родитель
cc2bb6968a
Коммит
e042323607
|
@ -1007,6 +1007,12 @@ int fsl_rio_setup(struct of_device *dev)
|
||||||
rio_register_mport(port);
|
rio_register_mport(port);
|
||||||
|
|
||||||
priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
|
priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
|
||||||
|
|
||||||
|
port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR))
|
||||||
|
& RIO_PEF_CTLS) >> 4;
|
||||||
|
dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
|
||||||
|
port->sys_size ? 65536 : 256);
|
||||||
|
|
||||||
priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
|
priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
|
||||||
+ RIO_ATMU_REGS_OFFSET);
|
+ RIO_ATMU_REGS_OFFSET);
|
||||||
priv->maint_atmu_regs = priv->atmu_regs + 1;
|
priv->maint_atmu_regs = priv->atmu_regs + 1;
|
||||||
|
|
|
@ -77,7 +77,7 @@ static int rionet_capable = 1;
|
||||||
* could be made into a hash table to save memory depending
|
* could be made into a hash table to save memory depending
|
||||||
* on system trade-offs.
|
* on system trade-offs.
|
||||||
*/
|
*/
|
||||||
static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
|
static struct rio_dev **rionet_active;
|
||||||
|
|
||||||
#define is_rionet_capable(pef, src_ops, dst_ops) \
|
#define is_rionet_capable(pef, src_ops, dst_ops) \
|
||||||
((pef & RIO_PEF_INB_MBOX) && \
|
((pef & RIO_PEF_INB_MBOX) && \
|
||||||
|
@ -195,7 +195,8 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eth->h_dest[0] & 0x01) {
|
if (eth->h_dest[0] & 0x01) {
|
||||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
|
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
|
||||||
|
i++)
|
||||||
if (rionet_active[i])
|
if (rionet_active[i])
|
||||||
rionet_queue_tx_msg(skb, ndev,
|
rionet_queue_tx_msg(skb, ndev,
|
||||||
rionet_active[i]);
|
rionet_active[i]);
|
||||||
|
@ -385,6 +386,8 @@ static void rionet_remove(struct rio_dev *rdev)
|
||||||
struct net_device *ndev = NULL;
|
struct net_device *ndev = NULL;
|
||||||
struct rionet_peer *peer, *tmp;
|
struct rionet_peer *peer, *tmp;
|
||||||
|
|
||||||
|
free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
|
||||||
|
__ilog2(sizeof(void *)) + 4 : 0);
|
||||||
unregister_netdev(ndev);
|
unregister_netdev(ndev);
|
||||||
kfree(ndev);
|
kfree(ndev);
|
||||||
|
|
||||||
|
@ -443,6 +446,15 @@ static int rionet_setup_netdev(struct rio_mport *mport)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
|
||||||
|
mport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0);
|
||||||
|
if (!rionet_active) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memset((void *)rionet_active, 0, sizeof(void *) *
|
||||||
|
RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
|
||||||
|
|
||||||
/* Set up private area */
|
/* Set up private area */
|
||||||
rnet = (struct rionet_private *)ndev->priv;
|
rnet = (struct rionet_private *)ndev->priv;
|
||||||
rnet->mport = mport;
|
rnet->mport = mport;
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
#
|
#
|
||||||
# RapidIO configuration
|
# RapidIO configuration
|
||||||
#
|
#
|
||||||
config RAPIDIO_8_BIT_TRANSPORT
|
|
||||||
bool "8-bit transport addressing"
|
|
||||||
depends on RAPIDIO
|
|
||||||
---help---
|
|
||||||
By default, the kernel assumes a 16-bit addressed RapidIO
|
|
||||||
network. By selecting this option, the kernel will support
|
|
||||||
an 8-bit addressed network.
|
|
||||||
|
|
||||||
config RAPIDIO_DISC_TIMEOUT
|
config RAPIDIO_DISC_TIMEOUT
|
||||||
int "Discovery timeout duration (seconds)"
|
int "Discovery timeout duration (seconds)"
|
||||||
depends on RAPIDIO
|
depends on RAPIDIO
|
||||||
|
|
|
@ -73,7 +73,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
|
||||||
|
|
||||||
rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
|
rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
|
||||||
|
|
||||||
return RIO_GET_DID(result);
|
return RIO_GET_DID(port->sys_size, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +88,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
|
||||||
static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
|
static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
|
||||||
{
|
{
|
||||||
rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
|
rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
|
||||||
RIO_SET_DID(did));
|
RIO_SET_DID(port->sys_size, did));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +100,8 @@ static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u
|
||||||
*/
|
*/
|
||||||
static void rio_local_set_device_id(struct rio_mport *port, u16 did)
|
static void rio_local_set_device_id(struct rio_mport *port, u16 did)
|
||||||
{
|
{
|
||||||
rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did));
|
rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size,
|
||||||
|
did));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -350,8 +351,18 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
|
||||||
rswitch->switchid = next_switchid;
|
rswitch->switchid = next_switchid;
|
||||||
rswitch->hopcount = hopcount;
|
rswitch->hopcount = hopcount;
|
||||||
rswitch->destid = destid;
|
rswitch->destid = destid;
|
||||||
|
rswitch->route_table = kzalloc(sizeof(u8)*
|
||||||
|
RIO_MAX_ROUTE_ENTRIES(port->sys_size),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!rswitch->route_table) {
|
||||||
|
kfree(rdev);
|
||||||
|
rdev = NULL;
|
||||||
|
kfree(rswitch);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* Initialize switch route table */
|
/* Initialize switch route table */
|
||||||
for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
|
for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
|
||||||
|
rdid++)
|
||||||
rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
|
rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
|
||||||
rdev->rswitch = rswitch;
|
rdev->rswitch = rswitch;
|
||||||
sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
|
sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
|
||||||
|
@ -480,7 +491,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
|
|
||||||
rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount,
|
rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), hopcount,
|
||||||
RIO_HOST_DID_LOCK_CSR, &result);
|
RIO_HOST_DID_LOCK_CSR, &result);
|
||||||
|
|
||||||
return (u16) (result & 0xffff);
|
return (u16) (result & 0xffff);
|
||||||
|
@ -571,14 +582,16 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to acquire device lock */
|
/* Attempt to acquire device lock */
|
||||||
rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
|
rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
|
||||||
|
hopcount,
|
||||||
RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
|
RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
|
||||||
while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
|
while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
|
||||||
< port->host_deviceid) {
|
< port->host_deviceid) {
|
||||||
/* Delay a bit */
|
/* Delay a bit */
|
||||||
mdelay(1);
|
mdelay(1);
|
||||||
/* Attempt to acquire device lock again */
|
/* Attempt to acquire device lock again */
|
||||||
rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
|
rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
|
||||||
|
hopcount,
|
||||||
RIO_HOST_DID_LOCK_CSR,
|
RIO_HOST_DID_LOCK_CSR,
|
||||||
port->host_deviceid);
|
port->host_deviceid);
|
||||||
}
|
}
|
||||||
|
@ -590,7 +603,9 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup new RIO device */
|
/* Setup new RIO device */
|
||||||
if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) {
|
rdev = rio_setup_device(net, port, RIO_ANY_DESTID(port->sys_size),
|
||||||
|
hopcount, 1);
|
||||||
|
if (rdev) {
|
||||||
/* Add device to the global and bus/net specific list. */
|
/* Add device to the global and bus/net specific list. */
|
||||||
list_add_tail(&rdev->net_list, &net->devices);
|
list_add_tail(&rdev->net_list, &net->devices);
|
||||||
} else
|
} else
|
||||||
|
@ -598,7 +613,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
||||||
|
|
||||||
if (rio_is_switch(rdev)) {
|
if (rio_is_switch(rdev)) {
|
||||||
next_switchid++;
|
next_switchid++;
|
||||||
sw_inport = rio_get_swpinfo_inport(port, RIO_ANY_DESTID, hopcount);
|
sw_inport = rio_get_swpinfo_inport(port,
|
||||||
|
RIO_ANY_DESTID(port->sys_size), hopcount);
|
||||||
rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
|
rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
|
||||||
port->host_deviceid, sw_inport);
|
port->host_deviceid, sw_inport);
|
||||||
rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
|
rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
|
||||||
|
@ -612,7 +628,8 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
||||||
}
|
}
|
||||||
|
|
||||||
num_ports =
|
num_ports =
|
||||||
rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount);
|
rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size),
|
||||||
|
hopcount);
|
||||||
pr_debug(
|
pr_debug(
|
||||||
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
|
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
|
||||||
rio_name(rdev), rdev->vid, rdev->did, num_ports);
|
rio_name(rdev), rdev->vid, rdev->did, num_ports);
|
||||||
|
@ -624,13 +641,15 @@ static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
||||||
cur_destid = next_destid;
|
cur_destid = next_destid;
|
||||||
|
|
||||||
if (rio_sport_is_active
|
if (rio_sport_is_active
|
||||||
(port, RIO_ANY_DESTID, hopcount, port_num)) {
|
(port, RIO_ANY_DESTID(port->sys_size), hopcount,
|
||||||
|
port_num)) {
|
||||||
pr_debug(
|
pr_debug(
|
||||||
"RIO: scanning device on port %d\n",
|
"RIO: scanning device on port %d\n",
|
||||||
port_num);
|
port_num);
|
||||||
rio_route_add_entry(port, rdev->rswitch,
|
rio_route_add_entry(port, rdev->rswitch,
|
||||||
RIO_GLOBAL_TABLE,
|
RIO_GLOBAL_TABLE,
|
||||||
RIO_ANY_DESTID, port_num);
|
RIO_ANY_DESTID(port->sys_size),
|
||||||
|
port_num);
|
||||||
|
|
||||||
if (rio_enum_peer(net, port, hopcount + 1) < 0)
|
if (rio_enum_peer(net, port, hopcount + 1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -735,7 +754,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
|
||||||
pr_debug(
|
pr_debug(
|
||||||
"RIO: scanning device on port %d\n",
|
"RIO: scanning device on port %d\n",
|
||||||
port_num);
|
port_num);
|
||||||
for (ndestid = 0; ndestid < RIO_ANY_DESTID;
|
for (ndestid = 0;
|
||||||
|
ndestid < RIO_ANY_DESTID(port->sys_size);
|
||||||
ndestid++) {
|
ndestid++) {
|
||||||
rio_route_get_entry(port, rdev->rswitch,
|
rio_route_get_entry(port, rdev->rswitch,
|
||||||
RIO_GLOBAL_TABLE,
|
RIO_GLOBAL_TABLE,
|
||||||
|
@ -917,7 +937,9 @@ static void rio_build_route_tables(void)
|
||||||
|
|
||||||
list_for_each_entry(rdev, &rio_devices, global_list)
|
list_for_each_entry(rdev, &rio_devices, global_list)
|
||||||
if (rio_is_switch(rdev))
|
if (rio_is_switch(rdev))
|
||||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
|
for (i = 0;
|
||||||
|
i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
|
||||||
|
i++) {
|
||||||
if (rio_route_get_entry
|
if (rio_route_get_entry
|
||||||
(rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
|
(rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
|
||||||
i, &sport) < 0)
|
i, &sport) < 0)
|
||||||
|
@ -981,7 +1003,8 @@ int rio_disc_mport(struct rio_mport *mport)
|
||||||
del_timer_sync(&rio_enum_timer);
|
del_timer_sync(&rio_enum_timer);
|
||||||
|
|
||||||
pr_debug("done\n");
|
pr_debug("done\n");
|
||||||
if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) {
|
if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
|
||||||
|
0) < 0) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"RIO: master port %d device has failed discovery\n",
|
"RIO: master port %d device has failed discovery\n",
|
||||||
mport->id);
|
mport->id);
|
||||||
|
|
|
@ -43,7 +43,8 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
|
||||||
if (!rdev->rswitch)
|
if (!rdev->rswitch)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
|
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
|
||||||
|
i++) {
|
||||||
if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
|
if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
|
||||||
continue;
|
continue;
|
||||||
str +=
|
str +=
|
||||||
|
|
|
@ -43,7 +43,7 @@ u16 rio_local_get_device_id(struct rio_mport *port)
|
||||||
|
|
||||||
rio_local_read_config_32(port, RIO_DID_CSR, &result);
|
rio_local_read_config_32(port, RIO_DID_CSR, &result);
|
||||||
|
|
||||||
return (RIO_GET_DID(result));
|
return (RIO_GET_DID(port->sys_size, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,10 +51,5 @@ extern struct rio_route_ops __end_rio_route_ops[];
|
||||||
DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
|
DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
|
||||||
vid, did, add_hook, get_hook)
|
vid, did, add_hook, get_hook)
|
||||||
|
|
||||||
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
|
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
|
||||||
#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16)
|
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
|
||||||
#define RIO_SET_DID(x) ((x & 0x000000ff) << 16)
|
|
||||||
#else
|
|
||||||
#define RIO_GET_DID(x) (x & 0xffff)
|
|
||||||
#define RIO_SET_DID(x) (x & 0xffff)
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/rio_regs.h>
|
#include <linux/rio_regs.h>
|
||||||
|
|
||||||
#define RIO_ANY_DESTID 0xff
|
|
||||||
#define RIO_NO_HOPCOUNT -1
|
#define RIO_NO_HOPCOUNT -1
|
||||||
#define RIO_INVALID_DESTID 0xffff
|
#define RIO_INVALID_DESTID 0xffff
|
||||||
|
|
||||||
|
@ -39,11 +38,8 @@
|
||||||
entry is invalid (no route
|
entry is invalid (no route
|
||||||
exists for the device ID) */
|
exists for the device ID) */
|
||||||
|
|
||||||
#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
|
#define RIO_MAX_ROUTE_ENTRIES(size) (size ? (1 << 16) : (1 << 8))
|
||||||
#define RIO_MAX_ROUTE_ENTRIES (1 << 8)
|
#define RIO_ANY_DESTID(size) (size ? 0xffff : 0xff)
|
||||||
#else
|
|
||||||
#define RIO_MAX_ROUTE_ENTRIES (1 << 16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RIO_MAX_MBOX 4
|
#define RIO_MAX_MBOX 4
|
||||||
#define RIO_MAX_MSG_SIZE 0x1000
|
#define RIO_MAX_MSG_SIZE 0x1000
|
||||||
|
@ -178,6 +174,10 @@ struct rio_mport {
|
||||||
unsigned char id; /* port ID, unique among all ports */
|
unsigned char id; /* port ID, unique among all ports */
|
||||||
unsigned char index; /* port index, unique among all port
|
unsigned char index; /* port index, unique among all port
|
||||||
interfaces of the same type */
|
interfaces of the same type */
|
||||||
|
unsigned int sys_size; /* RapidIO common transport system size.
|
||||||
|
* 0 - Small size. 256 devices.
|
||||||
|
* 1 - Large size, 65536 devices.
|
||||||
|
*/
|
||||||
unsigned char name[40];
|
unsigned char name[40];
|
||||||
void *priv; /* Master port private data */
|
void *priv; /* Master port private data */
|
||||||
};
|
};
|
||||||
|
@ -213,7 +213,7 @@ struct rio_switch {
|
||||||
u16 switchid;
|
u16 switchid;
|
||||||
u16 hopcount;
|
u16 hopcount;
|
||||||
u16 destid;
|
u16 destid;
|
||||||
u8 route_table[RIO_MAX_ROUTE_ENTRIES];
|
u8 *route_table;
|
||||||
int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
||||||
u16 table, u16 route_destid, u8 route_port);
|
u16 table, u16 route_destid, u8 route_port);
|
||||||
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче