mirror of
https://github.com/joel16/android_kernel_sony_msm8994_rework.git
synced 2025-01-15 13:39:25 +00:00
rapidio: add handling of redundant routes
Detects RIO link to the already enumerated device and properly sets links between device objects. Changes to the enumeration/discovery logic: 1. Use Master Enable bit to signal end of the enumeration - agents may start their discovery process as soon as they see this bit set (Component Tag register was used before for this purpose). 2. Enumerator sets Component Tag (!= 0) immediately during device setup. This allows to identify the device if the redundant route exists in a RIO system. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Thomas Moll <thomas.moll@sysgo.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Cc: Kumar Gala <galak@kernel.crashing.org> Cc: Micha Nelissen <micha@neli.hopto.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a3725c45c1
commit
af84ca38af
@ -50,6 +50,7 @@
|
|||||||
#define RIO_ATMU_REGS_OFFSET 0x10c00
|
#define RIO_ATMU_REGS_OFFSET 0x10c00
|
||||||
#define RIO_P_MSG_REGS_OFFSET 0x11000
|
#define RIO_P_MSG_REGS_OFFSET 0x11000
|
||||||
#define RIO_S_MSG_REGS_OFFSET 0x13000
|
#define RIO_S_MSG_REGS_OFFSET 0x13000
|
||||||
|
#define RIO_GCCSR 0x13c
|
||||||
#define RIO_ESCSR 0x158
|
#define RIO_ESCSR 0x158
|
||||||
#define RIO_CCSR 0x15c
|
#define RIO_CCSR 0x15c
|
||||||
#define RIO_LTLEDCSR 0x0608
|
#define RIO_LTLEDCSR 0x0608
|
||||||
@ -1471,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev)
|
|||||||
port->host_deviceid = fsl_rio_get_hdid(port->id);
|
port->host_deviceid = fsl_rio_get_hdid(port->id);
|
||||||
|
|
||||||
port->priv = priv;
|
port->priv = priv;
|
||||||
|
port->phys_efptr = 0x100;
|
||||||
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);
|
||||||
@ -1518,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev)
|
|||||||
dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
|
dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
|
||||||
port->sys_size ? 65536 : 256);
|
port->sys_size ? 65536 : 256);
|
||||||
|
|
||||||
|
if (port->host_deviceid >= 0)
|
||||||
|
out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
|
||||||
|
RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
|
||||||
|
else
|
||||||
|
out_be32(priv->regs_win + RIO_GCCSR, 0x00000000);
|
||||||
|
|
||||||
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;
|
||||||
|
@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock);
|
|||||||
static int next_destid = 0;
|
static int next_destid = 0;
|
||||||
static int next_switchid = 0;
|
static int next_switchid = 0;
|
||||||
static int next_net = 0;
|
static int next_net = 0;
|
||||||
static int next_comptag;
|
static int next_comptag = 1;
|
||||||
|
|
||||||
static struct timer_list rio_enum_timer =
|
static struct timer_list rio_enum_timer =
|
||||||
TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
|
TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
|
||||||
@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port)
|
|||||||
u32 result;
|
u32 result;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* Assign component tag to all devices */
|
|
||||||
next_comptag = 1;
|
|
||||||
rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++);
|
|
||||||
|
|
||||||
list_for_each_entry(rdev, &rio_devices, global_list) {
|
|
||||||
/* Mark device as discovered */
|
|
||||||
rio_read_config_32(rdev,
|
|
||||||
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
|
|
||||||
&result);
|
|
||||||
rio_write_config_32(rdev,
|
|
||||||
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
|
|
||||||
result | RIO_PORT_GEN_DISCOVERED);
|
|
||||||
|
|
||||||
rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag);
|
|
||||||
rdev->comp_tag = next_comptag++;
|
|
||||||
if (next_comptag >= 0x10000) {
|
|
||||||
pr_err("RIO: Component Tag Counter Overflow\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release host device id locks */
|
/* Release host device id locks */
|
||||||
rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
|
rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
|
||||||
port->host_deviceid);
|
port->host_deviceid);
|
||||||
@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port)
|
|||||||
rdev->vid, rdev->did);
|
rdev->vid, rdev->did);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark device as discovered and enable master */
|
||||||
|
rio_read_config_32(rdev,
|
||||||
|
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
|
||||||
|
&result);
|
||||||
|
result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER;
|
||||||
|
rio_write_config_32(rdev,
|
||||||
|
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
|
||||||
|
result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -430,6 +418,17 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
|
|||||||
rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
|
rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
|
||||||
&rdev->dst_ops);
|
&rdev->dst_ops);
|
||||||
|
|
||||||
|
if (do_enum) {
|
||||||
|
/* Assign component tag to device */
|
||||||
|
if (next_comptag >= 0x10000) {
|
||||||
|
pr_err("RIO: Component Tag Counter Overflow\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
rio_mport_write_config_32(port, destid, hopcount,
|
||||||
|
RIO_COMPONENT_TAG_CSR, next_comptag);
|
||||||
|
rdev->comp_tag = next_comptag++;
|
||||||
|
}
|
||||||
|
|
||||||
if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
|
if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
|
||||||
if (do_enum) {
|
if (do_enum) {
|
||||||
rio_set_device_id(port, destid, hopcount, next_destid);
|
rio_set_device_id(port, destid, hopcount, next_destid);
|
||||||
@ -725,21 +724,6 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
|
|||||||
return (u16) (result & 0xffff);
|
return (u16) (result & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* rio_net_add_mport- Add a master port to a RIO network
|
|
||||||
* @net: RIO network
|
|
||||||
* @port: Master port to add
|
|
||||||
*
|
|
||||||
* Adds a master port to the network list of associated master
|
|
||||||
* ports..
|
|
||||||
*/
|
|
||||||
static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port)
|
|
||||||
{
|
|
||||||
spin_lock(&rio_global_list_lock);
|
|
||||||
list_add_tail(&port->nnode, &net->mports);
|
|
||||||
spin_unlock(&rio_global_list_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rio_enum_peer- Recursively enumerate a RIO network through a master port
|
* rio_enum_peer- Recursively enumerate a RIO network through a master port
|
||||||
* @net: RIO network being enumerated
|
* @net: RIO network being enumerated
|
||||||
@ -760,6 +744,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||||||
int sw_inport;
|
int sw_inport;
|
||||||
struct rio_dev *rdev;
|
struct rio_dev *rdev;
|
||||||
u16 destid;
|
u16 destid;
|
||||||
|
u32 regval;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
if (rio_mport_chk_dev_access(port,
|
if (rio_mport_chk_dev_access(port,
|
||||||
@ -772,9 +757,21 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||||||
pr_debug("RIO: PE already discovered by this host\n");
|
pr_debug("RIO: PE already discovered by this host\n");
|
||||||
/*
|
/*
|
||||||
* Already discovered by this host. Add it as another
|
* Already discovered by this host. Add it as another
|
||||||
* master port for the current network.
|
* link to the existing device.
|
||||||
*/
|
*/
|
||||||
rio_net_add_mport(net, port);
|
rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size),
|
||||||
|
hopcount, RIO_COMPONENT_TAG_CSR, ®val);
|
||||||
|
|
||||||
|
if (regval) {
|
||||||
|
rdev = rio_get_comptag((regval & 0xffff), NULL);
|
||||||
|
|
||||||
|
if (rdev && prev && rio_is_switch(prev)) {
|
||||||
|
pr_debug("RIO: redundant path to %s\n",
|
||||||
|
rio_name(rdev));
|
||||||
|
prev->rswitch->nextdev[prev_port] = rdev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,10 +922,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
|
|||||||
*/
|
*/
|
||||||
static int rio_enum_complete(struct rio_mport *port)
|
static int rio_enum_complete(struct rio_mport *port)
|
||||||
{
|
{
|
||||||
u32 tag_csr;
|
u32 regval;
|
||||||
|
|
||||||
rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
|
rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
|
||||||
return (tag_csr & 0xffff) ? 1 : 0;
|
®val);
|
||||||
|
return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -991,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ndestid == RIO_ANY_DESTID(port->sys_size))
|
||||||
|
continue;
|
||||||
rio_unlock_device(port, destid, hopcount);
|
rio_unlock_device(port, destid, hopcount);
|
||||||
if (rio_disc_peer
|
if (rio_disc_peer
|
||||||
(net, port, ndestid, hopcount + 1) < 0)
|
(net, port, ndestid, hopcount + 1) < 0)
|
||||||
@ -1163,6 +1163,10 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
|
|||||||
/* Enable Input Output Port (transmitter reviever) */
|
/* Enable Input Output Port (transmitter reviever) */
|
||||||
rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
|
rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
/* Set component tag for host */
|
||||||
|
rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR,
|
||||||
|
next_comptag++);
|
||||||
|
|
||||||
if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
|
if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
|
||||||
/* A higher priority host won enumeration, bail. */
|
/* A higher priority host won enumeration, bail. */
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
|
@ -443,7 +443,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local,
|
|||||||
* @from is not %NULL, searches continue from next device on the global
|
* @from is not %NULL, searches continue from next device on the global
|
||||||
* list.
|
* list.
|
||||||
*/
|
*/
|
||||||
static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
|
struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
|
||||||
{
|
{
|
||||||
struct list_head *n;
|
struct list_head *n;
|
||||||
struct rio_dev *rdev;
|
struct rio_dev *rdev;
|
||||||
@ -507,7 +507,7 @@ static int
|
|||||||
rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
|
rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
int p_port, rc = -EIO;
|
int p_port, dstid, rc = -EIO;
|
||||||
struct rio_dev *prev = NULL;
|
struct rio_dev *prev = NULL;
|
||||||
|
|
||||||
/* Find switch with failed RIO link */
|
/* Find switch with failed RIO link */
|
||||||
@ -522,20 +522,18 @@ rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
|
|||||||
if (prev == NULL)
|
if (prev == NULL)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
/* Find port with failed RIO link */
|
dstid = (rdev->pef & RIO_PEF_SWITCH) ?
|
||||||
for (p_port = 0;
|
rdev->rswitch->destid : rdev->destid;
|
||||||
p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo); p_port++)
|
p_port = prev->rswitch->route_table[dstid];
|
||||||
if (prev->rswitch->nextdev[p_port] == rdev)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo)) {
|
if (p_port != RIO_INVALID_ROUTE) {
|
||||||
pr_debug("RIO: link failed on [%s]-P%d\n",
|
pr_debug("RIO: link failed on [%s]-P%d\n",
|
||||||
rio_name(prev), p_port);
|
rio_name(prev), p_port);
|
||||||
*nrdev = prev;
|
*nrdev = prev;
|
||||||
*npnum = p_port;
|
*npnum = p_port;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else
|
} else
|
||||||
pr_debug("RIO: failed to trace route to %s\n", rio_name(prev));
|
pr_debug("RIO: failed to trace route to %s\n", rio_name(rdev));
|
||||||
err_out:
|
err_out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
|
|||||||
extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
|
extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
|
||||||
u8 hopcount, u16 table);
|
u8 hopcount, u16 table);
|
||||||
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);
|
||||||
|
|
||||||
/* Structures internal to the RIO core code */
|
/* Structures internal to the RIO core code */
|
||||||
extern struct device_attribute rio_dev_attrs[];
|
extern struct device_attribute rio_dev_attrs[];
|
||||||
|
@ -177,6 +177,7 @@ enum rio_phy_type {
|
|||||||
* @index: Port index, unique among all port interfaces of the same type
|
* @index: Port index, unique among all port interfaces of the same type
|
||||||
* @sys_size: RapidIO common transport system size
|
* @sys_size: RapidIO common transport system size
|
||||||
* @phy_type: RapidIO phy type
|
* @phy_type: RapidIO phy type
|
||||||
|
* @phys_efptr: RIO port extended features pointer
|
||||||
* @name: Port name string
|
* @name: Port name string
|
||||||
* @priv: Master port private data
|
* @priv: Master port private data
|
||||||
*/
|
*/
|
||||||
@ -198,6 +199,7 @@ struct rio_mport {
|
|||||||
* 1 - Large size, 65536 devices.
|
* 1 - Large size, 65536 devices.
|
||||||
*/
|
*/
|
||||||
enum rio_phy_type phy_type; /* RapidIO phy type */
|
enum rio_phy_type phy_type; /* RapidIO phy type */
|
||||||
|
u32 phys_efptr;
|
||||||
unsigned char name[40];
|
unsigned char name[40];
|
||||||
void *priv; /* Master port private data */
|
void *priv; /* Master port private data */
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user