diff options
| author | Alexandre Bounine <alexandre.bounine@idt.com> | 2010-10-27 18:34:34 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 21:03:16 -0400 |
| commit | af84ca38aff94061dd0711edbb99b0900a9c28fd (patch) | |
| tree | 31f51e9106c0a0944ec168dc25399f12ab2fa527 | |
| parent | a3725c45c114bd06e091802f90533332d1e93819 (diff) | |
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>
| -rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 8 | ||||
| -rw-r--r-- | drivers/rapidio/rio-scan.c | 88 | ||||
| -rw-r--r-- | drivers/rapidio/rio.c | 16 | ||||
| -rw-r--r-- | drivers/rapidio/rio.h | 1 | ||||
| -rw-r--r-- | include/linux/rio.h | 2 |
5 files changed, 64 insertions, 51 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index ed2ec7154917..9725369d432a 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #define RIO_ATMU_REGS_OFFSET 0x10c00 | 50 | #define RIO_ATMU_REGS_OFFSET 0x10c00 |
| 51 | #define RIO_P_MSG_REGS_OFFSET 0x11000 | 51 | #define RIO_P_MSG_REGS_OFFSET 0x11000 |
| 52 | #define RIO_S_MSG_REGS_OFFSET 0x13000 | 52 | #define RIO_S_MSG_REGS_OFFSET 0x13000 |
| 53 | #define RIO_GCCSR 0x13c | ||
| 53 | #define RIO_ESCSR 0x158 | 54 | #define RIO_ESCSR 0x158 |
| 54 | #define RIO_CCSR 0x15c | 55 | #define RIO_CCSR 0x15c |
| 55 | #define RIO_LTLEDCSR 0x0608 | 56 | #define RIO_LTLEDCSR 0x0608 |
| @@ -1471,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 1471 | port->host_deviceid = fsl_rio_get_hdid(port->id); | 1472 | port->host_deviceid = fsl_rio_get_hdid(port->id); |
| 1472 | 1473 | ||
| 1473 | port->priv = priv; | 1474 | port->priv = priv; |
| 1475 | port->phys_efptr = 0x100; | ||
| 1474 | rio_register_mport(port); | 1476 | rio_register_mport(port); |
| 1475 | 1477 | ||
| 1476 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); | 1478 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); |
| @@ -1518,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 1518 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", | 1520 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", |
| 1519 | port->sys_size ? 65536 : 256); | 1521 | port->sys_size ? 65536 : 256); |
| 1520 | 1522 | ||
| 1523 | if (port->host_deviceid >= 0) | ||
| 1524 | out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | | ||
| 1525 | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); | ||
| 1526 | else | ||
| 1527 | out_be32(priv->regs_win + RIO_GCCSR, 0x00000000); | ||
| 1528 | |||
| 1521 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win | 1529 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win |
| 1522 | + RIO_ATMU_REGS_OFFSET); | 1530 | + RIO_ATMU_REGS_OFFSET); |
| 1523 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 1531 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index e3efdf93df5a..1eb82c4c712e 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
| @@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock); | |||
| 48 | static int next_destid = 0; | 48 | static int next_destid = 0; |
| 49 | static int next_switchid = 0; | 49 | static int next_switchid = 0; |
| 50 | static int next_net = 0; | 50 | static int next_net = 0; |
| 51 | static int next_comptag; | 51 | static int next_comptag = 1; |
| 52 | 52 | ||
| 53 | static struct timer_list rio_enum_timer = | 53 | static struct timer_list rio_enum_timer = |
| 54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); | 54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); |
| @@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port) | |||
| 121 | u32 result; | 121 | u32 result; |
| 122 | int ret = 0; | 122 | int ret = 0; |
| 123 | 123 | ||
| 124 | /* Assign component tag to all devices */ | ||
| 125 | next_comptag = 1; | ||
| 126 | rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++); | ||
| 127 | |||
| 128 | list_for_each_entry(rdev, &rio_devices, global_list) { | ||
| 129 | /* Mark device as discovered */ | ||
| 130 | rio_read_config_32(rdev, | ||
| 131 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 132 | &result); | ||
| 133 | rio_write_config_32(rdev, | ||
| 134 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 135 | result | RIO_PORT_GEN_DISCOVERED); | ||
| 136 | |||
| 137 | rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag); | ||
| 138 | rdev->comp_tag = next_comptag++; | ||
| 139 | if (next_comptag >= 0x10000) { | ||
| 140 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Release host device id locks */ | 124 | /* Release host device id locks */ |
| 146 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, | 125 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, |
| 147 | port->host_deviceid); | 126 | port->host_deviceid); |
| @@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port) | |||
| 162 | rdev->vid, rdev->did); | 141 | rdev->vid, rdev->did); |
| 163 | ret = -EINVAL; | 142 | ret = -EINVAL; |
| 164 | } | 143 | } |
| 144 | |||
| 145 | /* Mark device as discovered and enable master */ | ||
| 146 | rio_read_config_32(rdev, | ||
| 147 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 148 | &result); | ||
| 149 | result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER; | ||
| 150 | rio_write_config_32(rdev, | ||
| 151 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 152 | result); | ||
| 165 | } | 153 | } |
| 166 | 154 | ||
| 167 | return ret; | 155 | return ret; |
| @@ -430,6 +418,17 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
| 430 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, | 418 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, |
| 431 | &rdev->dst_ops); | 419 | &rdev->dst_ops); |
| 432 | 420 | ||
| 421 | if (do_enum) { | ||
| 422 | /* Assign component tag to device */ | ||
| 423 | if (next_comptag >= 0x10000) { | ||
| 424 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
| 425 | goto cleanup; | ||
| 426 | } | ||
| 427 | rio_mport_write_config_32(port, destid, hopcount, | ||
| 428 | RIO_COMPONENT_TAG_CSR, next_comptag); | ||
| 429 | rdev->comp_tag = next_comptag++; | ||
| 430 | } | ||
| 431 | |||
| 433 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { | 432 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { |
| 434 | if (do_enum) { | 433 | if (do_enum) { |
| 435 | rio_set_device_id(port, destid, hopcount, next_destid); | 434 | rio_set_device_id(port, destid, hopcount, next_destid); |
| @@ -726,21 +725,6 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) | |||
| 726 | } | 725 | } |
| 727 | 726 | ||
| 728 | /** | 727 | /** |
| 729 | * rio_net_add_mport- Add a master port to a RIO network | ||
| 730 | * @net: RIO network | ||
| 731 | * @port: Master port to add | ||
| 732 | * | ||
| 733 | * Adds a master port to the network list of associated master | ||
| 734 | * ports.. | ||
| 735 | */ | ||
| 736 | static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) | ||
| 737 | { | ||
| 738 | spin_lock(&rio_global_list_lock); | ||
| 739 | list_add_tail(&port->nnode, &net->mports); | ||
| 740 | spin_unlock(&rio_global_list_lock); | ||
| 741 | } | ||
| 742 | |||
| 743 | /** | ||
| 744 | * rio_enum_peer- Recursively enumerate a RIO network through a master port | 728 | * rio_enum_peer- Recursively enumerate a RIO network through a master port |
| 745 | * @net: RIO network being enumerated | 729 | * @net: RIO network being enumerated |
| 746 | * @port: Master port to send transactions | 730 | * @port: Master port to send transactions |
| @@ -760,6 +744,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
| 760 | int sw_inport; | 744 | int sw_inport; |
| 761 | struct rio_dev *rdev; | 745 | struct rio_dev *rdev; |
| 762 | u16 destid; | 746 | u16 destid; |
| 747 | u32 regval; | ||
| 763 | int tmp; | 748 | int tmp; |
| 764 | 749 | ||
| 765 | if (rio_mport_chk_dev_access(port, | 750 | 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, | |||
| 772 | pr_debug("RIO: PE already discovered by this host\n"); | 757 | pr_debug("RIO: PE already discovered by this host\n"); |
| 773 | /* | 758 | /* |
| 774 | * Already discovered by this host. Add it as another | 759 | * Already discovered by this host. Add it as another |
| 775 | * master port for the current network. | 760 | * link to the existing device. |
| 776 | */ | 761 | */ |
| 777 | rio_net_add_mport(net, port); | 762 | rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), |
| 763 | hopcount, RIO_COMPONENT_TAG_CSR, ®val); | ||
| 764 | |||
| 765 | if (regval) { | ||
| 766 | rdev = rio_get_comptag((regval & 0xffff), NULL); | ||
| 767 | |||
| 768 | if (rdev && prev && rio_is_switch(prev)) { | ||
| 769 | pr_debug("RIO: redundant path to %s\n", | ||
| 770 | rio_name(rdev)); | ||
| 771 | prev->rswitch->nextdev[prev_port] = rdev; | ||
| 772 | } | ||
| 773 | } | ||
