aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-04 20:16:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-05 14:05:22 -0400
commita7071efc20567f4b6c454ff93ca80daf51bf93e9 (patch)
tree3c59852343f27c89ab7f3527f1fd8e4ba0fc8833 /drivers/rapidio
parentfa3dbaa0109d9fff23f7fd28c245bee880757ecd (diff)
rapidio: use device lists handling on per-net basis
Modify handling of device lists to resolve issues caused by using single global list of RIO devices during enumeration/discovery. The most common sign of existing issue is incorrect contents of switch routing tables in systems with multiple mport controllers while single-port configuration performs as expected. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r--drivers/rapidio/rio-scan.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 0a27253c9215..8b7c4bce7a4a 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -38,7 +38,6 @@
38#include "rio.h" 38#include "rio.h"
39 39
40LIST_HEAD(rio_devices); 40LIST_HEAD(rio_devices);
41static LIST_HEAD(rio_switches);
42 41
43static void rio_init_em(struct rio_dev *rdev); 42static void rio_init_em(struct rio_dev *rdev);
44 43
@@ -104,14 +103,15 @@ static void rio_local_set_device_id(struct rio_mport *port, u16 did)
104 103
105/** 104/**
106 * rio_clear_locks- Release all host locks and signal enumeration complete 105 * rio_clear_locks- Release all host locks and signal enumeration complete
107 * @port: Master port to issue transaction 106 * @net: RIO network to run on
108 * 107 *
109 * Marks the component tag CSR on each device with the enumeration 108 * Marks the component tag CSR on each device with the enumeration
110 * complete flag. When complete, it then release the host locks on 109 * complete flag. When complete, it then release the host locks on
111 * each device. Returns 0 on success or %-EINVAL on failure. 110 * each device. Returns 0 on success or %-EINVAL on failure.
112 */ 111 */
113static int rio_clear_locks(struct rio_mport *port) 112static int rio_clear_locks(struct rio_net *net)
114{ 113{
114 struct rio_mport *port = net->hport;
115 struct rio_dev *rdev; 115 struct rio_dev *rdev;
116 u32 result; 116 u32 result;
117 int ret = 0; 117 int ret = 0;
@@ -126,7 +126,7 @@ static int rio_clear_locks(struct rio_mport *port)
126 result); 126 result);
127 ret = -EINVAL; 127 ret = -EINVAL;
128 } 128 }
129 list_for_each_entry(rdev, &rio_devices, global_list) { 129 list_for_each_entry(rdev, &net->devices, net_list) {
130 rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, 130 rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
131 port->host_deviceid); 131 port->host_deviceid);
132 rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); 132 rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result);
@@ -479,7 +479,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
479 rswitch->clr_table(port, destid, hopcount, 479 rswitch->clr_table(port, destid, hopcount,
480 RIO_GLOBAL_TABLE); 480 RIO_GLOBAL_TABLE);
481 481
482 list_add_tail(&rswitch->node, &rio_switches); 482 list_add_tail(&rswitch->node, &net->switches);
483 483
484 } else { 484 } else {
485 if (do_enum) 485 if (do_enum)
@@ -1058,6 +1058,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1058 if (net) { 1058 if (net) {
1059 INIT_LIST_HEAD(&net->node); 1059 INIT_LIST_HEAD(&net->node);
1060 INIT_LIST_HEAD(&net->devices); 1060 INIT_LIST_HEAD(&net->devices);
1061 INIT_LIST_HEAD(&net->switches);
1061 INIT_LIST_HEAD(&net->mports); 1062 INIT_LIST_HEAD(&net->mports);
1062 list_add_tail(&port->nnode, &net->mports); 1063 list_add_tail(&port->nnode, &net->mports);
1063 net->hport = port; 1064 net->hport = port;
@@ -1068,24 +1069,24 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1068 1069
1069/** 1070/**
1070 * rio_update_route_tables- Updates route tables in switches 1071 * rio_update_route_tables- Updates route tables in switches
1071 * @port: Master port associated with the RIO network 1072 * @net: RIO network to run update on
1072 * 1073 *
1073 * For each enumerated device, ensure that each switch in a system 1074 * For each enumerated device, ensure that each switch in a system
1074 * has correct routing entries. Add routes for devices that where 1075 * has correct routing entries. Add routes for devices that where
1075 * unknown dirung the first enumeration pass through the switch. 1076 * unknown dirung the first enumeration pass through the switch.
1076 */ 1077 */
1077static void rio_update_route_tables(struct rio_mport *port) 1078static void rio_update_route_tables(struct rio_net *net)
1078{ 1079{
1079 struct rio_dev *rdev, *swrdev; 1080 struct rio_dev *rdev, *swrdev;
1080 struct rio_switch *rswitch; 1081 struct rio_switch *rswitch;
1081 u8 sport; 1082 u8 sport;
1082 u16 destid; 1083 u16 destid;
1083 1084
1084 list_for_each_entry(rdev, &rio_devices, global_list) { 1085 list_for_each_entry(rdev, &net->devices, net_list) {
1085 1086
1086 destid = rdev->destid; 1087 destid = rdev->destid;
1087 1088
1088 list_for_each_entry(rswitch, &rio_switches, node) { 1089 list_for_each_entry(rswitch, &net->switches, node) {
1089 1090
1090 if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) 1091 if (rio_is_switch(rdev) && (rdev->rswitch == rswitch))
1091 continue; 1092 continue;
@@ -1181,12 +1182,12 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1181 printk(KERN_INFO 1182 printk(KERN_INFO
1182 "RIO: master port %d device has lost enumeration to a remote host\n", 1183 "RIO: master port %d device has lost enumeration to a remote host\n",
1183 mport->id); 1184 mport->id);
1184 rio_clear_locks(mport); 1185 rio_clear_locks(net);
1185 rc = -EBUSY; 1186 rc = -EBUSY;
1186 goto out; 1187 goto out;
1187 } 1188 }
1188 rio_update_route_tables(mport); 1189 rio_update_route_tables(net);
1189 rio_clear_locks(mport); 1190 rio_clear_locks(net);
1190 rio_pw_enable(mport, 1); 1191 rio_pw_enable(mport, 1);
1191 } else { 1192 } else {
1192 printk(KERN_INFO "RIO: master port %d link inactive\n", 1193 printk(KERN_INFO "RIO: master port %d link inactive\n",
@@ -1200,33 +1201,34 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1200 1201
1201/** 1202/**
1202 * rio_build_route_tables- Generate route tables from switch route entries 1203 * rio_build_route_tables- Generate route tables from switch route entries
1204 * @net: RIO network to run route tables scan on
1203 * 1205 *
1204 * For each switch device, generate a route table by copying existing 1206 * For each switch device, generate a route table by copying existing
1205 * route entries from the switch. 1207 * route entries from the switch.
1206 */ 1208 */
1207static void rio_build_route_tables(void) 1209static void rio_build_route_tables(struct rio_net *net)
1208{ 1210{
1211 struct rio_switch *rswitch;
1209 struct rio_dev *rdev; 1212 struct rio_dev *rdev;
1210 int i; 1213 int i;
1211 u8 sport; 1214 u8 sport;
1212 1215
1213 list_for_each_entry(rdev, &rio_devices, global_list) 1216 list_for_each_entry(rswitch, &net->switches, node) {
1214 if (rio_is_switch(rdev)) { 1217 rdev = sw_to_rio_dev(rswitch);
1215 rio_lock_device(rdev->net->hport, rdev->destid,
1216 rdev->hopcount, 1000);
1217 for (i = 0;
1218 i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
1219 i++) {
1220 if (rio_route_get_entry(rdev,
1221 RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
1222 continue;
1223 rdev->rswitch->route_table[i] = sport;
1224 }
1225 1218
1226 rio_unlock_device(rdev->net->hport, 1219 rio_lock_device(net->hport, rdev->destid,
1227 rdev->destid, 1220 rdev->hopcount, 1000);
1228 rdev->hopcount); 1221 for (i = 0;
1222 i < RIO_MAX_ROUTE_ENTRIES(net->hport->sys_size);
1223 i++) {
1224 if (rio_route_get_entry(rdev, RIO_GLOBAL_TABLE,
1225 i, &sport, 0) < 0)
1226 continue;
1227 rswitch->route_table[i] = sport;
1229 } 1228 }
1229
1230 rio_unlock_device(net->hport, rdev->destid, rdev->hopcount);
1231 }
1230} 1232}
1231 1233
1232/** 1234/**
@@ -1284,7 +1286,7 @@ enum_done:
1284 goto bail; 1286 goto bail;
1285 } 1287 }
1286 1288
1287 rio_build_route_tables(); 1289 rio_build_route_tables(net);
1288 } 1290 }
1289 1291
1290 return 0; 1292 return 0;