diff options
author | Alexandre Bounine <alexandre.bounine@idt.com> | 2010-10-27 18:34:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 21:03:15 -0400 |
commit | 68fe4df5d21294401959fa61d5a7094705ed8f6f (patch) | |
tree | 28cd3609514f3a7b1e78e627b069aa5669bc7fd0 | |
parent | ae05cbd5adef897d405ce8f90484c1239f79e086 (diff) |
rapidio: add relation links between RIO device structures
Create back and forward links between RIO devices. These links are
intended for use by error management and hot-plug extensions. Links for
redundant RIO connections between switches are not set (will be fixed in a
separate patch).
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-- | drivers/rapidio/rio-scan.c | 56 | ||||
-rw-r--r-- | include/linux/rio.h | 4 |
2 files changed, 27 insertions, 33 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index d09c359844f3..d2ea01872d6a 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -444,7 +444,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
444 | 444 | ||
445 | /* If a PE has both switch and other functions, show it as a switch */ | 445 | /* If a PE has both switch and other functions, show it as a switch */ |
446 | if (rio_is_switch(rdev)) { | 446 | if (rio_is_switch(rdev)) { |
447 | rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); | 447 | rswitch = kzalloc(sizeof(*rswitch) + |
448 | RIO_GET_TOTAL_PORTS(rdev->swpinfo) * | ||
449 | sizeof(rswitch->nextdev[0]), | ||
450 | GFP_KERNEL); | ||
448 | if (!rswitch) | 451 | if (!rswitch) |
449 | goto cleanup; | 452 | goto cleanup; |
450 | rswitch->switchid = next_switchid; | 453 | rswitch->switchid = next_switchid; |
@@ -723,25 +726,6 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) | |||
723 | } | 726 | } |
724 | 727 | ||
725 | /** | 728 | /** |
726 | * rio_get_swpinfo_tports- Gets total number of ports on the switch | ||
727 | * @mport: Master port to send transaction | ||
728 | * @destid: Destination ID associated with the switch | ||
729 | * @hopcount: Number of hops to the device | ||
730 | * | ||
731 | * Returns total numbers of ports implemented by the switch device. | ||
732 | */ | ||
733 | static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, | ||
734 | u8 hopcount) | ||
735 | { | ||
736 | u32 result; | ||
737 | |||
738 | rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, | ||
739 | &result); | ||
740 | |||
741 | return RIO_GET_TOTAL_PORTS(result); | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * rio_net_add_mport- Add a master port to a RIO network | 729 | * rio_net_add_mport- Add a master port to a RIO network |
746 | * @net: RIO network | 730 | * @net: RIO network |
747 | * @port: Master port to add | 731 | * @port: Master port to add |
@@ -761,15 +745,16 @@ static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) | |||
761 | * @net: RIO network being enumerated | 745 | * @net: RIO network being enumerated |
762 | * @port: Master port to send transactions | 746 | * @port: Master port to send transactions |
763 | * @hopcount: Number of hops into the network | 747 | * @hopcount: Number of hops into the network |
748 | * @prev: Previous RIO device connected to the enumerated one | ||
749 | * @prev_port: Port on previous RIO device | ||
764 | * | 750 | * |
765 | * Recursively enumerates a RIO network. Transactions are sent via the | 751 | * Recursively enumerates a RIO network. Transactions are sent via the |
766 | * master port passed in @port. | 752 | * master port passed in @port. |
767 | */ | 753 | */ |
768 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | 754 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, |
769 | u8 hopcount) | 755 | u8 hopcount, struct rio_dev *prev, int prev_port) |
770 | { | 756 | { |
771 | int port_num; | 757 | int port_num; |
772 | int num_ports; | ||
773 | int cur_destid; | 758 | int cur_destid; |
774 | int sw_destid; | 759 | int sw_destid; |
775 | int sw_inport; | 760 | int sw_inport; |
@@ -814,6 +799,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
814 | if (rdev) { | 799 | if (rdev) { |
815 | /* Add device to the global and bus/net specific list. */ | 800 | /* Add device to the global and bus/net specific list. */ |
816 | list_add_tail(&rdev->net_list, &net->devices); | 801 | list_add_tail(&rdev->net_list, &net->devices); |
802 | rdev->prev = prev; | ||
803 | if (prev && rio_is_switch(prev)) | ||
804 | prev->rswitch->nextdev[prev_port] = rdev; | ||
817 | } else | 805 | } else |
818 | return -1; | 806 | return -1; |
819 | 807 | ||
@@ -832,14 +820,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
832 | rdev->rswitch->route_table[destid] = sw_inport; | 820 | rdev->rswitch->route_table[destid] = sw_inport; |
833 | } | 821 | } |
834 | 822 | ||
835 | num_ports = | ||
836 | rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size), | ||
837 | hopcount); | ||
838 | pr_debug( | 823 | pr_debug( |
839 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 824 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
840 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 825 | rio_name(rdev), rdev->vid, rdev->did, |
826 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); | ||
841 | sw_destid = next_destid; | 827 | sw_destid = next_destid; |
842 | for (port_num = 0; port_num < num_ports; port_num++) { | 828 | for (port_num = 0; |
829 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); | ||
830 | port_num++) { | ||
843 | /*Enable Input Output Port (transmitter reviever)*/ | 831 | /*Enable Input Output Port (transmitter reviever)*/ |
844 | rio_enable_rx_tx_port(port, 0, | 832 | rio_enable_rx_tx_port(port, 0, |
845 | RIO_ANY_DESTID(port->sys_size), | 833 | RIO_ANY_DESTID(port->sys_size), |
@@ -864,7 +852,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
864 | RIO_ANY_DESTID(port->sys_size), | 852 | RIO_ANY_DESTID(port->sys_size), |
865 | port_num, 0); | 853 | port_num, 0); |
866 | 854 | ||
867 | if (rio_enum_peer(net, port, hopcount + 1) < 0) | 855 | if (rio_enum_peer(net, port, hopcount + 1, |
856 | rdev, port_num) < 0) | ||
868 | return -1; | 857 | return -1; |
869 | 858 | ||
870 | /* Update routing tables */ | 859 | /* Update routing tables */ |
@@ -951,7 +940,6 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
951 | u8 hopcount) | 940 | u8 hopcount) |
952 | { | 941 | { |
953 | u8 port_num, route_port; | 942 | u8 port_num, route_port; |
954 | int num_ports; | ||
955 | struct rio_dev *rdev; | 943 | struct rio_dev *rdev; |
956 | u16 ndestid; | 944 | u16 ndestid; |
957 | 945 | ||
@@ -968,11 +956,13 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
968 | /* Associated destid is how we accessed this switch */ | 956 | /* Associated destid is how we accessed this switch */ |
969 | rdev->rswitch->destid = destid; | 957 | rdev->rswitch->destid = destid; |
970 | 958 | ||
971 | num_ports = rio_get_swpinfo_tports(port, destid, hopcount); | ||
972 | pr_debug( | 959 | pr_debug( |
973 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 960 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
974 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 961 | rio_name(rdev), rdev->vid, rdev->did, |
975 | for (port_num = 0; port_num < num_ports; port_num++) { | 962 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); |
963 | for (port_num = 0; | ||
964 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); | ||
965 | port_num++) { | ||
976 | if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num) | 966 | if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num) |
977 | continue; | 967 | continue; |
978 | 968 | ||
@@ -1167,7 +1157,7 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1167 | /* Enable Input Output Port (transmitter reviever) */ | 1157 | /* Enable Input Output Port (transmitter reviever) */ |
1168 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | 1158 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); |
1169 | 1159 | ||
1170 | if (rio_enum_peer(net, mport, 0) < 0) { | 1160 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { |
1171 | /* A higher priority host won enumeration, bail. */ | 1161 | /* A higher priority host won enumeration, bail. */ |
1172 | printk(KERN_INFO | 1162 | printk(KERN_INFO |
1173 | "RIO: master port %d device has lost enumeration to a remote host\n", | 1163 | "RIO: master port %d device has lost enumeration to a remote host\n", |
diff --git a/include/linux/rio.h b/include/linux/rio.h index ffdfe5ad43bf..8d9e66dc7969 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h | |||
@@ -99,6 +99,7 @@ union rio_pw_msg; | |||
99 | * @riores: RIO resources this device owns | 99 | * @riores: RIO resources this device owns |
100 | * @pwcback: port-write callback function for this device | 100 | * @pwcback: port-write callback function for this device |
101 | * @destid: Network destination ID | 101 | * @destid: Network destination ID |
102 | * @prev: Previous RIO device connected to the current one | ||
102 | */ | 103 | */ |
103 | struct rio_dev { | 104 | struct rio_dev { |
104 | struct list_head global_list; /* node in list of all RIO devices */ | 105 | struct list_head global_list; /* node in list of all RIO devices */ |
@@ -125,6 +126,7 @@ struct rio_dev { | |||
125 | struct resource riores[RIO_MAX_DEV_RESOURCES]; | 126 | struct resource riores[RIO_MAX_DEV_RESOURCES]; |
126 | int (*pwcback) (struct rio_dev *rdev, union rio_pw_msg *msg, int step); | 127 | int (*pwcback) (struct rio_dev *rdev, union rio_pw_msg *msg, int step); |
127 | u16 destid; | 128 | u16 destid; |
129 | struct rio_dev *prev; | ||
128 | }; | 130 | }; |
129 | 131 | ||
130 | #define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) | 132 | #define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) |
@@ -232,6 +234,7 @@ struct rio_net { | |||
232 | * @get_domain: Callback for switch-specific domain get function | 234 | * @get_domain: Callback for switch-specific domain get function |
233 | * @em_init: Callback for switch-specific error management initialization function | 235 | * @em_init: Callback for switch-specific error management initialization function |
234 | * @em_handle: Callback for switch-specific error management handler function | 236 | * @em_handle: Callback for switch-specific error management handler function |
237 | * @nextdev: Array of per-port pointers to the next attached device | ||
235 | */ | 238 | */ |
236 | struct rio_switch { | 239 | struct rio_switch { |
237 | struct list_head node; | 240 | struct list_head node; |
@@ -253,6 +256,7 @@ struct rio_switch { | |||
253 | u8 *sw_domain); | 256 | u8 *sw_domain); |
254 | int (*em_init) (struct rio_dev *dev); | 257 | int (*em_init) (struct rio_dev *dev); |
255 | int (*em_handle) (struct rio_dev *dev, u8 swport); | 258 | int (*em_handle) (struct rio_dev *dev, u8 swport); |
259 | struct rio_dev *nextdev[0]; | ||
256 | }; | 260 | }; |
257 | 261 | ||
258 | /* Low-level architecture-dependent routines */ | 262 | /* Low-level architecture-dependent routines */ |