Commit af84ca38aff94061dd0711edbb99b0900a9c28fd

Authored by Alexandre Bounine
Committed by Linus Torvalds
1 parent a3725c45c1

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>

Showing 5 changed files with 64 additions and 51 deletions Side-by-side Diff

arch/powerpc/sysdev/fsl_rio.c
... ... @@ -50,6 +50,7 @@
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
... ... @@ -1471,6 +1472,7 @@
1471 1472 port->host_deviceid = fsl_rio_get_hdid(port->id);
1472 1473  
1473 1474 port->priv = priv;
  1475 + port->phys_efptr = 0x100;
1474 1476 rio_register_mport(port);
1475 1477  
1476 1478 priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
... ... @@ -1517,6 +1519,12 @@
1517 1519 & RIO_PEF_CTLS) >> 4;
1518 1520 dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
1519 1521 port->sys_size ? 65536 : 256);
  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);
1520 1528  
1521 1529 priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
1522 1530 + RIO_ATMU_REGS_OFFSET);
drivers/rapidio/rio-scan.c
... ... @@ -48,7 +48,7 @@
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,27 +121,6 @@
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);
... ... @@ -162,6 +141,15 @@
162 141 rdev->vid, rdev->did);
163 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 155 return ret;
... ... @@ -430,6 +418,17 @@
430 418 rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
431 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 432 if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
434 433 if (do_enum) {
435 434 rio_set_device_id(port, destid, hopcount, next_destid);
... ... @@ -726,21 +725,6 @@
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 728 * rio_enum_peer- Recursively enumerate a RIO network through a master port
745 729 * @net: RIO network being enumerated
746 730 * @port: Master port to send transactions
... ... @@ -760,6 +744,7 @@
760 744 int sw_inport;
761 745 struct rio_dev *rdev;
762 746 u16 destid;
  747 + u32 regval;
763 748 int tmp;
764 749  
765 750 if (rio_mport_chk_dev_access(port,
766 751  
... ... @@ -772,9 +757,21 @@
772 757 pr_debug("RIO: PE already discovered by this host\n");
773 758 /*
774 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, &regval);
  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 + }
  774 +
778 775 return 0;
779 776 }
780 777  
781 778  
... ... @@ -925,10 +922,11 @@
925 922 */
926 923 static int rio_enum_complete(struct rio_mport *port)
927 924 {
928   - u32 tag_csr;
  925 + u32 regval;
929 926  
930   - rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
931   - return (tag_csr & 0xffff) ? 1 : 0;
  927 + rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
  928 + &regval);
  929 + return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
932 930 }
933 931  
934 932 /**
... ... @@ -991,6 +989,8 @@
991 989 break;
992 990 }
993 991  
  992 + if (ndestid == RIO_ANY_DESTID(port->sys_size))
  993 + continue;
994 994 rio_unlock_device(port, destid, hopcount);
995 995 if (rio_disc_peer
996 996 (net, port, ndestid, hopcount + 1) < 0)
... ... @@ -1162,6 +1162,10 @@
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. */
drivers/rapidio/rio.c
... ... @@ -443,7 +443,7 @@
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,7 +507,7 @@
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 */
514 514  
515 515  
... ... @@ -522,20 +522,18 @@
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 }
drivers/rapidio/rio.h
... ... @@ -38,6 +38,7 @@
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[];
... ... @@ -177,6 +177,7 @@
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 */
... ... @@ -198,6 +199,7 @@
198 199 * 1 - Large size, 65536 devices.
199 200 */
200 201 enum rio_phy_type phy_type; /* RapidIO phy type */
  202 + u32 phys_efptr;
201 203 unsigned char name[40];
202 204 void *priv; /* Master port private data */
203 205 };