aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-04 20:16:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-05 14:05:22 -0400
commitfa3dbaa0109d9fff23f7fd28c245bee880757ecd (patch)
treed4f0f15935e4743ce72c813add174df7f9cac167 /drivers/rapidio
parent8d4630dcf41214719cf44a94f8eec2a83f69943b (diff)
rapidio: fix blocking wait for discovery ready
The following set of patches provides modifications targeting support of multiple RapidIO master port (mport) devices on a CPU-side of RapidIO-capable board. While the RapidIO subsystem code has definitions suitable for multi-controller/multi-net support, the existing implementation cannot be considered ready for multiple mport configurations. =========== NOTES: ============= a) The patches below do not address RapidIO side view of multiport processing elements defined in Part 6 of RapidIO spec Rev.2.1 (section 6.4.1). These devices have Base Device ID CSR (0x60) and Component Tag CSR (0x6C) shared by all SRIO ports. For example, Freescale's P4080, P3041 and P5020 have a dual-port SRIO controller implemented according the specification. Enumeration/discovery of such devices from RapidIO side may require device-specific fixups. b) Devices referenced above may also require implementation specific code to setup a host device ID for mport device. These operations are not addressed by patches in this package. ================================= Details about provided patches: 1. Fix blocking wait for discovery ready While it does not happen on PowerPC based platforms, there is possibility of stalled CPU warning dump on x86 based platforms that run RapidIO discovery process if they wait too long for being enumerated. Currently users can avoid it by disabling the soft-lockup detector using "nosoftlockup" kernel parameter OR by ensuring that enumeration is completed before soft-lockup is detected. This patch eliminates blocking wait and keeps a scheduler running. It also is required for patch 3 below which introduces asynchronous discovery process. 2. Use device lists handling on per-net basis This patch allows to correctly support multiple RapidIO nets and resolves possible issues caused by using single global list of devices during RapidIO system 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. The patch does not eliminate the global RapidIO device list but changes some routines in enumeration/discovery to use per-net device lists instead. This way compatibility with upper layer RIO routines is preserved. 3. Run discovery as an asynchronous process This patch modifies RapidIO initialization routine to asynchronously run the discovery process for each corresponding mport. This allows having an arbitrary order of enumerating and discovering mports without creating a deadlock situation if an enumerator port was registered after a discovering one. On boards with multiple discovering mports it also eliminates order dependency between mports and may reduce total time of RapidIO subsystem initialization. Making netID matching to mportID ensures consistent netID assignment in multiport RapidIO systems with asynchronous discovery process (global counter implementation is affected by race between threads). 4. Rework RIONET to support multiple RIO master ports In the current version of the driver rionet_probe() has comment "XXX Make multi-net safe". Now it is a good time to address this comment. This patch makes RIONET driver multi-net safe/capable by introducing per-net lists of RapidIO network peers. It also enables to register network adapters for all available mport devices. 5. Add destination ID allocation mechanism The patch replaces a single global destination ID counter with per-net allocation mechanism to allow independent destID management for each available RapidIO network. Using bitmap based mechanism instead of counters allows destination ID release and reuse in systems that support hot-swap. This patch: Fix blocking wait loop in the RapidIO discovery routine to avoid warning dumps about stalled CPU on x86 platforms. 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.c62
1 files changed, 20 insertions, 42 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 02e686b4c19a..0a27253c9215 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -31,6 +31,7 @@
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/timer.h> 33#include <linux/timer.h>
34#include <linux/sched.h>
34#include <linux/jiffies.h> 35#include <linux/jiffies.h>
35#include <linux/slab.h> 36#include <linux/slab.h>
36 37
@@ -39,8 +40,6 @@
39LIST_HEAD(rio_devices); 40LIST_HEAD(rio_devices);
40static LIST_HEAD(rio_switches); 41static LIST_HEAD(rio_switches);
41 42
42static void rio_enum_timeout(unsigned long);
43
44static void rio_init_em(struct rio_dev *rdev); 43static void rio_init_em(struct rio_dev *rdev);
45 44
46DEFINE_SPINLOCK(rio_global_list_lock); 45DEFINE_SPINLOCK(rio_global_list_lock);
@@ -49,9 +48,6 @@ static int next_destid = 0;
49static int next_net = 0; 48static int next_net = 0;
50static int next_comptag = 1; 49static int next_comptag = 1;
51 50
52static struct timer_list rio_enum_timer =
53TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
54
55static int rio_mport_phys_table[] = { 51static int rio_mport_phys_table[] = {
56 RIO_EFB_PAR_EP_ID, 52 RIO_EFB_PAR_EP_ID,
57 RIO_EFB_PAR_EP_REC_ID, 53 RIO_EFB_PAR_EP_REC_ID,
@@ -1234,20 +1230,6 @@ static void rio_build_route_tables(void)
1234} 1230}
1235 1231
1236/** 1232/**
1237 * rio_enum_timeout- Signal that enumeration timed out
1238 * @data: Address of timeout flag.
1239 *
1240 * When the enumeration complete timer expires, set a flag that
1241 * signals to the discovery process that enumeration did not
1242 * complete in a sane amount of time.
1243 */
1244static void rio_enum_timeout(unsigned long data)
1245{
1246 /* Enumeration timed out, set flag */
1247 *(int *)data = 1;
1248}
1249
1250/**
1251 * rio_disc_mport- Start discovery through a master port 1233 * rio_disc_mport- Start discovery through a master port
1252 * @mport: Master port to send transactions 1234 * @mport: Master port to send transactions
1253 * 1235 *
@@ -1260,34 +1242,33 @@ static void rio_enum_timeout(unsigned long data)
1260int __devinit rio_disc_mport(struct rio_mport *mport) 1242int __devinit rio_disc_mport(struct rio_mport *mport)
1261{ 1243{
1262 struct rio_net *net = NULL; 1244 struct rio_net *net = NULL;
1263 int enum_timeout_flag = 0; 1245 unsigned long to_end;
1264 1246
1265 printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, 1247 printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id,
1266 mport->name); 1248 mport->name);
1267 1249
1268 /* If master port has an active link, allocate net and discover peers */ 1250 /* If master port has an active link, allocate net and discover peers */
1269 if (rio_mport_is_active(mport)) { 1251 if (rio_mport_is_active(mport)) {
1270 if (!(net = rio_alloc_net(mport))) { 1252 pr_debug("RIO: wait for enumeration to complete...\n");
1271 printk(KERN_ERR "RIO: Failed to allocate new net\n");
1272 goto bail;
1273 }
1274 1253
1275 pr_debug("RIO: wait for enumeration complete..."); 1254 to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
1276 1255 while (time_before(jiffies, to_end)) {
1277 rio_enum_timer.expires = 1256 if (rio_enum_complete(mport))
1278 jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; 1257 goto enum_done;
1279 rio_enum_timer.data = (unsigned long)&enum_timeout_flag; 1258 schedule_timeout_uninterruptible(msecs_to_jiffies(10));
1280 add_timer(&rio_enum_timer);
1281 while (!rio_enum_complete(mport)) {
1282 mdelay(1);
1283 if (enum_timeout_flag) {
1284 del_timer_sync(&rio_enum_timer);
1285 goto timeout;
1286 }
1287 } 1259 }
1288 del_timer_sync(&rio_enum_timer);
1289 1260
1290 pr_debug("done\n"); 1261 pr_debug("RIO: discovery timeout on mport %d %s\n",
1262 mport->id, mport->name);
1263 goto bail;
1264enum_done:
1265 pr_debug("RIO: ... enumeration done\n");
1266
1267 net = rio_alloc_net(mport);
1268 if (!net) {
1269 printk(KERN_ERR "RIO: Failed to allocate new net\n");
1270 goto bail;
1271 }
1291 1272
1292 /* Read DestID assigned by enumerator */ 1273 /* Read DestID assigned by enumerator */
1293 rio_local_read_config_32(mport, RIO_DID_CSR, 1274 rio_local_read_config_32(mport, RIO_DID_CSR,
@@ -1307,9 +1288,6 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
1307 } 1288 }
1308 1289
1309 return 0; 1290 return 0;
1310 1291bail:
1311 timeout:
1312 pr_debug("timeout\n");
1313 bail:
1314 return -EBUSY; 1292 return -EBUSY;
1315} 1293}