Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alexandre Bounine and committed by
Linus Torvalds
af84ca38 a3725c45

+64 -51
+8
arch/powerpc/sysdev/fsl_rio.c
··· 50 50 #define RIO_ATMU_REGS_OFFSET 0x10c00 51 51 #define RIO_P_MSG_REGS_OFFSET 0x11000 52 52 #define RIO_S_MSG_REGS_OFFSET 0x13000 53 + #define RIO_GCCSR 0x13c 53 54 #define RIO_ESCSR 0x158 54 55 #define RIO_CCSR 0x15c 55 56 #define RIO_LTLEDCSR 0x0608 ··· 1472 1471 port->host_deviceid = fsl_rio_get_hdid(port->id); 1473 1472 1474 1473 port->priv = priv; 1474 + port->phys_efptr = 0x100; 1475 1475 rio_register_mport(port); 1476 1476 1477 1477 priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); ··· 1519 1517 & RIO_PEF_CTLS) >> 4; 1520 1518 dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", 1521 1519 port->sys_size ? 65536 : 256); 1520 + 1521 + if (port->host_deviceid >= 0) 1522 + out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | 1523 + RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); 1524 + else 1525 + out_be32(priv->regs_win + RIO_GCCSR, 0x00000000); 1522 1526 1523 1527 priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win 1524 1528 + RIO_ATMU_REGS_OFFSET);
+46 -42
drivers/rapidio/rio-scan.c
··· 48 48 static int next_destid = 0; 49 49 static int next_switchid = 0; 50 50 static int next_net = 0; 51 - static int next_comptag; 51 + static int next_comptag = 1; 52 52 53 53 static struct timer_list rio_enum_timer = 54 54 TIMER_INITIALIZER(rio_enum_timeout, 0, 0); ··· 121 121 u32 result; 122 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 124 /* Release host device id locks */ 146 125 rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 147 126 port->host_deviceid); ··· 141 162 rdev->vid, rdev->did); 142 163 ret = -EINVAL; 143 164 } 165 + 166 + /* Mark device as discovered and enable master */ 167 + rio_read_config_32(rdev, 168 + rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, 169 + &result); 170 + result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER; 171 + rio_write_config_32(rdev, 172 + rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, 173 + result); 144 174 } 145 175 146 176 return ret; ··· 417 429 &rdev->src_ops); 418 430 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, 419 431 &rdev->dst_ops); 432 + 433 + if (do_enum) { 434 + /* Assign component tag to device */ 435 + if (next_comptag >= 0x10000) { 436 + pr_err("RIO: Component Tag Counter Overflow\n"); 437 + goto cleanup; 438 + } 439 + rio_mport_write_config_32(port, destid, hopcount, 440 + RIO_COMPONENT_TAG_CSR, next_comptag); 441 + rdev->comp_tag = next_comptag++; 442 + } 420 443 421 444 if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { 422 445 if (do_enum) { ··· 725 726 } 726 727 727 728 /** 728 - * rio_net_add_mport- Add a master port to a RIO network 729 - * @net: RIO network 730 - * @port: Master port to add 731 - * 732 - * Adds a master port to the network list of associated master 733 - * ports.. 734 - */ 735 - static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) 736 - { 737 - spin_lock(&rio_global_list_lock); 738 - list_add_tail(&port->nnode, &net->mports); 739 - spin_unlock(&rio_global_list_lock); 740 - } 741 - 742 - /** 743 729 * rio_enum_peer- Recursively enumerate a RIO network through a master port 744 730 * @net: RIO network being enumerated 745 731 * @port: Master port to send transactions ··· 744 760 int sw_inport; 745 761 struct rio_dev *rdev; 746 762 u16 destid; 763 + u32 regval; 747 764 int tmp; 748 765 749 766 if (rio_mport_chk_dev_access(port, ··· 757 772 pr_debug("RIO: PE already discovered by this host\n"); 758 773 /* 759 774 * Already discovered by this host. Add it as another 760 - * master port for the current network. 775 + * link to the existing device. 761 776 */ 762 - rio_net_add_mport(net, port); 777 + rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), 778 + hopcount, RIO_COMPONENT_TAG_CSR, &regval); 779 + 780 + if (regval) { 781 + rdev = rio_get_comptag((regval & 0xffff), NULL); 782 + 783 + if (rdev && prev && rio_is_switch(prev)) { 784 + pr_debug("RIO: redundant path to %s\n", 785 + rio_name(rdev)); 786 + prev->rswitch->nextdev[prev_port] = rdev; 787 + } 788 + } 789 + 763 790 return 0; 764 791 } 765 792 ··· 922 925 */ 923 926 static int rio_enum_complete(struct rio_mport *port) 924 927 { 925 - u32 tag_csr; 928 + u32 regval; 926 929 927 - rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); 928 - return (tag_csr & 0xffff) ? 1 : 0; 930 + rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR, 931 + &regval); 932 + return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0; 929 933 } 930 934 931 935 /** ··· 989 991 break; 990 992 } 991 993 994 + if (ndestid == RIO_ANY_DESTID(port->sys_size)) 995 + continue; 992 996 rio_unlock_device(port, destid, hopcount); 993 997 if (rio_disc_peer 994 998 (net, port, ndestid, hopcount + 1) < 0) ··· 1162 1162 1163 1163 /* Enable Input Output Port (transmitter reviever) */ 1164 1164 rio_enable_rx_tx_port(mport, 1, 0, 0, 0); 1165 + 1166 + /* Set component tag for host */ 1167 + rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, 1168 + next_comptag++); 1165 1169 1166 1170 if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { 1167 1171 /* A higher priority host won enumeration, bail. */
+7 -9
drivers/rapidio/rio.c
··· 443 443 * @from is not %NULL, searches continue from next device on the global 444 444 * list. 445 445 */ 446 - static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) 446 + struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) 447 447 { 448 448 struct list_head *n; 449 449 struct rio_dev *rdev; ··· 507 507 rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) 508 508 { 509 509 u32 result; 510 - int p_port, rc = -EIO; 510 + int p_port, dstid, rc = -EIO; 511 511 struct rio_dev *prev = NULL; 512 512 513 513 /* Find switch with failed RIO link */ ··· 522 522 if (prev == NULL) 523 523 goto err_out; 524 524 525 - /* Find port with failed RIO link */ 526 - for (p_port = 0; 527 - p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo); p_port++) 528 - if (prev->rswitch->nextdev[p_port] == rdev) 529 - break; 525 + dstid = (rdev->pef & RIO_PEF_SWITCH) ? 526 + rdev->rswitch->destid : rdev->destid; 527 + p_port = prev->rswitch->route_table[dstid]; 530 528 531 - if (p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo)) { 529 + if (p_port != RIO_INVALID_ROUTE) { 532 530 pr_debug("RIO: link failed on [%s]-P%d\n", 533 531 rio_name(prev), p_port); 534 532 *nrdev = prev; 535 533 *npnum = p_port; 536 534 rc = 0; 537 535 } else 538 - pr_debug("RIO: failed to trace route to %s\n", rio_name(prev)); 536 + pr_debug("RIO: failed to trace route to %s\n", rio_name(rdev)); 539 537 err_out: 540 538 return rc; 541 539 }
+1
drivers/rapidio/rio.h
··· 38 38 extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, 39 39 u8 hopcount, u16 table); 40 40 extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); 41 + extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from); 41 42 42 43 /* Structures internal to the RIO core code */ 43 44 extern struct device_attribute rio_dev_attrs[];
+2
include/linux/rio.h
··· 177 177 * @index: Port index, unique among all port interfaces of the same type 178 178 * @sys_size: RapidIO common transport system size 179 179 * @phy_type: RapidIO phy type 180 + * @phys_efptr: RIO port extended features pointer 180 181 * @name: Port name string 181 182 * @priv: Master port private data 182 183 */ ··· 199 198 * 1 - Large size, 65536 devices. 200 199 */ 201 200 enum rio_phy_type phy_type; /* RapidIO phy type */ 201 + u32 phys_efptr; 202 202 unsigned char name[40]; 203 203 void *priv; /* Master port private data */ 204 204 };