diff options
-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 ed2ec715491..9725369d432 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 e3efdf93df5..1eb82c4c712 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 | } | ||
774 | |||
778 | return 0; | 775 | return 0; |
779 | } | 776 | } |
780 | 777 | ||
@@ -925,10 +922,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
925 | */ | 922 | */ |
926 | static int rio_enum_complete(struct rio_mport *port) | 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); | 927 | rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR, |
931 | return (tag_csr & 0xffff) ? 1 : 0; | 928 | ®val); |
929 | return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0; | ||
932 | } | 930 | } |
933 | 931 | ||
934 | /** | 932 | /** |
@@ -991,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
991 | break; | 989 | break; |
992 | } | 990 | } |
993 | 991 | ||
992 | if (ndestid == RIO_ANY_DESTID(port->sys_size)) | ||
993 | continue; | ||
994 | rio_unlock_device(port, destid, hopcount); | 994 | rio_unlock_device(port, destid, hopcount); |
995 | if (rio_disc_peer | 995 | if (rio_disc_peer |
996 | (net, port, ndestid, hopcount + 1) < 0) | 996 | (net, port, ndestid, hopcount + 1) < 0) |
@@ -1163,6 +1163,10 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1163 | /* Enable Input Output Port (transmitter reviever) */ | 1163 | /* Enable Input Output Port (transmitter reviever) */ |
1164 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | 1164 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); |
1165 | 1165 | ||
1166 | /* Set component tag for host */ | ||
1167 | rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, | ||
1168 | next_comptag++); | ||
1169 | |||
1166 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { | 1170 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { |
1167 | /* A higher priority host won enumeration, bail. */ | 1171 | /* A higher priority host won enumeration, bail. */ |
1168 | printk(KERN_INFO | 1172 | printk(KERN_INFO |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index fa5e3cbe4c8..7f18a65c4ed 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -443,7 +443,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local, | |||
443 | * @from is not %NULL, searches continue from next device on the global | 443 | * @from is not %NULL, searches continue from next device on the global |
444 | * list. | 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 | struct list_head *n; | 448 | struct list_head *n; |
449 | struct rio_dev *rdev; | 449 | struct rio_dev *rdev; |
@@ -507,7 +507,7 @@ static int | |||
507 | rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) | 507 | rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) |
508 | { | 508 | { |
509 | u32 result; | 509 | u32 result; |
510 | int p_port, rc = -EIO; | 510 | int p_port, dstid, rc = -EIO; |
511 | struct rio_dev *prev = NULL; | 511 | struct rio_dev *prev = NULL; |
512 | 512 | ||
513 | /* Find switch with failed RIO link */ | 513 | /* Find switch with failed RIO link */ |
@@ -522,20 +522,18 @@ rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) | |||
522 | if (prev == NULL) | 522 | if (prev == NULL) |
523 | goto err_out; | 523 | goto err_out; |
524 | 524 | ||
525 | /* Find port with failed RIO link */ | 525 | dstid = (rdev->pef & RIO_PEF_SWITCH) ? |
526 | for (p_port = 0; | 526 | rdev->rswitch->destid : rdev->destid; |
527 | p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo); p_port++) | 527 | p_port = prev->rswitch->route_table[dstid]; |
528 | if (prev->rswitch->nextdev[p_port] == rdev) | ||
529 | break; | ||
530 | 528 | ||
531 | if (p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo)) { | 529 | if (p_port != RIO_INVALID_ROUTE) { |
532 | pr_debug("RIO: link failed on [%s]-P%d\n", | 530 | pr_debug("RIO: link failed on [%s]-P%d\n", |
533 | rio_name(prev), p_port); | 531 | rio_name(prev), p_port); |
534 | *nrdev = prev; | 532 | *nrdev = prev; |
535 | *npnum = p_port; | 533 | *npnum = p_port; |
536 | rc = 0; | 534 | rc = 0; |
537 | } else | 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 | err_out: | 537 | err_out: |
540 | return rc; | 538 | return rc; |
541 | } | 539 | } |
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index d249a1205c7..b1af414f15e 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h | |||
@@ -38,6 +38,7 @@ extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, | |||
38 | extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, | 38 | extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, |
39 | u8 hopcount, u16 table); | 39 | u8 hopcount, u16 table); |
40 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); | 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 | /* Structures internal to the RIO core code */ | 43 | /* Structures internal to the RIO core code */ |
43 | extern struct device_attribute rio_dev_attrs[]; | 44 | extern struct device_attribute rio_dev_attrs[]; |
diff --git a/include/linux/rio.h b/include/linux/rio.h index 4fa5e3d2b11..0bed941f9b1 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h | |||
@@ -177,6 +177,7 @@ enum rio_phy_type { | |||
177 | * @index: Port index, unique among all port interfaces of the same type | 177 | * @index: Port index, unique among all port interfaces of the same type |
178 | * @sys_size: RapidIO common transport system size | 178 | * @sys_size: RapidIO common transport system size |
179 | * @phy_type: RapidIO phy type | 179 | * @phy_type: RapidIO phy type |
180 | * @phys_efptr: RIO port extended features pointer | ||
180 | * @name: Port name string | 181 | * @name: Port name string |
181 | * @priv: Master port private data | 182 | * @priv: Master port private data |
182 | */ | 183 | */ |
@@ -198,6 +199,7 @@ struct rio_mport { | |||
198 | * 1 - Large size, 65536 devices. | 199 | * 1 - Large size, 65536 devices. |
199 | */ | 200 | */ |
200 | enum rio_phy_type phy_type; /* RapidIO phy type */ | 201 | enum rio_phy_type phy_type; /* RapidIO phy type */ |
202 | u32 phys_efptr; | ||
201 | unsigned char name[40]; | 203 | unsigned char name[40]; |
202 | void *priv; /* Master port private data */ | 204 | void *priv; /* Master port private data */ |
203 | }; | 205 | }; |