[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:
Zhang Wei 2008-04-18 13:33:42 -07:00 коммит произвёл Paul Mackerras
Родитель cc2bb6968a
Коммит e042323607
8 изменённых файлов: 71 добавлений и 42 удалений

Просмотреть файл

@ -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,