aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2013-07-03 18:08:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:04 -0400
commit2ec3ba69faf301fb599e3651515e808e8efa533e (patch)
tree953f10726fd0cd61fec02082233c6097287d7257
parent36f0efbbe8e21c153dfc2f94c91f89ab06fd64c5 (diff)
rapidio: convert switch drivers to modules
Rework RapidIO switch drivers to add an option to build them as loadable kernel modules. This patch removes RapidIO-specific vmlinux section and converts switch drivers to be compatible with LDM driver registration method. To simplify registration of device-specific callback routines this patch introduces rio_switch_ops data structure. The sw_sysfs() callback is removed from the list of device-specific operations because under the new structure its functions can be handled by switch driver's probe() and remove() routines. If a specific switch device driver is not loaded the RapidIO subsystem core will use default standard-based operations to configure a switch. Because the current implementation of RapidIO enumeration/discovery method relies on availability of device-specific operations for error management, switch device drivers must be loaded before the RapidIO enumeration/discovery starts. This patch also moves several common routines from enumeration/discovery module into the RapidIO core code to make switch-specific operations accessible to all components of RapidIO subsystem. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Cc: Kumar Gala <galak@kernel.crashing.org> Cc: Andre van Herk <andre.van.herk@Prodrive.nl> Cc: Micha Nelissen <micha.nelissen@Prodrive.nl> Cc: Stef van Os <stef.van.os@Prodrive.nl> Cc: Jean Delvare <jdelvare@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rapidio/Kconfig5
-rw-r--r--drivers/rapidio/rio-scan.c171
-rw-r--r--drivers/rapidio/rio-sysfs.c4
-rw-r--r--drivers/rapidio/rio.c286
-rw-r--r--drivers/rapidio/rio.h41
-rw-r--r--drivers/rapidio/switches/Kconfig12
-rw-r--r--drivers/rapidio/switches/idt_gen2.c98
-rw-r--r--drivers/rapidio/switches/idtcps.c86
-rw-r--r--drivers/rapidio/switches/tsi568.c71
-rw-r--r--drivers/rapidio/switches/tsi57x.c81
-rw-r--r--include/asm-generic/vmlinux.lds.h7
-rw-r--r--include/linux/rio.h51
12 files changed, 568 insertions, 345 deletions
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index 5ab056494bbe..3e3be57e9a1a 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -67,4 +67,9 @@ config RAPIDIO_ENUM_BASIC
67 67
68endchoice 68endchoice
69 69
70menu "RapidIO Switch drivers"
71 depends on RAPIDIO
72
70source "drivers/rapidio/switches/Kconfig" 73source "drivers/rapidio/switches/Kconfig"
74
75endmenu
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 4b9b15ee8596..913950212605 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -406,6 +406,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
406 rio_mport_write_config_32(port, destid, hopcount, 406 rio_mport_write_config_32(port, destid, hopcount,
407 RIO_COMPONENT_TAG_CSR, next_comptag); 407 RIO_COMPONENT_TAG_CSR, next_comptag);
408 rdev->comp_tag = next_comptag++; 408 rdev->comp_tag = next_comptag++;
409 rdev->do_enum = true;
409 } else { 410 } else {
410 rio_mport_read_config_32(port, destid, hopcount, 411 rio_mport_read_config_32(port, destid, hopcount,
411 RIO_COMPONENT_TAG_CSR, 412 RIO_COMPONENT_TAG_CSR,
@@ -434,6 +435,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
434 rswitch = rdev->rswitch; 435 rswitch = rdev->rswitch;
435 rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; 436 rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID;
436 rswitch->port_ok = 0; 437 rswitch->port_ok = 0;
438 spin_lock_init(&rswitch->lock);
437 rswitch->route_table = kzalloc(sizeof(u8)* 439 rswitch->route_table = kzalloc(sizeof(u8)*
438 RIO_MAX_ROUTE_ENTRIES(port->sys_size), 440 RIO_MAX_ROUTE_ENTRIES(port->sys_size),
439 GFP_KERNEL); 441 GFP_KERNEL);
@@ -445,11 +447,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
445 rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 447 rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
446 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 448 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
447 rswitch->switchid); 449 rswitch->switchid);
448 rio_switch_init(rdev, do_enum);
449 450
450 if (do_enum && rswitch->clr_table) 451 if (do_enum)
451 rswitch->clr_table(port, destid, hopcount, 452 rio_route_clr_table(rdev, RIO_GLOBAL_TABLE, 0);
452 RIO_GLOBAL_TABLE);
453 453
454 list_add_tail(&rswitch->node, &net->switches); 454 list_add_tail(&rswitch->node, &net->switches);
455 455
@@ -533,156 +533,6 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
533} 533}
534 534
535/** 535/**
536 * rio_lock_device - Acquires host device lock for specified device
537 * @port: Master port to send transaction
538 * @destid: Destination ID for device/switch
539 * @hopcount: Hopcount to reach switch
540 * @wait_ms: Max wait time in msec (0 = no timeout)
541 *
542 * Attepts to acquire host device lock for specified device
543 * Returns 0 if device lock acquired or EINVAL if timeout expires.
544 */
545static int
546rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms)
547{
548 u32 result;
549 int tcnt = 0;
550
551 /* Attempt to acquire device lock */
552 rio_mport_write_config_32(port, destid, hopcount,
553 RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
554 rio_mport_read_config_32(port, destid, hopcount,
555 RIO_HOST_DID_LOCK_CSR, &result);
556
557 while (result != port->host_deviceid) {
558 if (wait_ms != 0 && tcnt == wait_ms) {
559 pr_debug("RIO: timeout when locking device %x:%x\n",
560 destid, hopcount);
561 return -EINVAL;
562 }
563
564 /* Delay a bit */
565 mdelay(1);
566 tcnt++;
567 /* Try to acquire device lock again */
568 rio_mport_write_config_32(port, destid,
569 hopcount,
570 RIO_HOST_DID_LOCK_CSR,
571 port->host_deviceid);
572 rio_mport_read_config_32(port, destid,
573 hopcount,
574 RIO_HOST_DID_LOCK_CSR, &result);
575 }
576
577 return 0;
578}
579
580/**
581 * rio_unlock_device - Releases host device lock for specified device
582 * @port: Master port to send transaction
583 * @destid: Destination ID for device/switch
584 * @hopcount: Hopcount to reach switch
585 *
586 * Returns 0 if device lock released or EINVAL if fails.
587 */
588static int
589rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
590{
591 u32 result;
592
593 /* Release device lock */
594 rio_mport_write_config_32(port, destid,
595 hopcount,
596 RIO_HOST_DID_LOCK_CSR,
597 port->host_deviceid);
598 rio_mport_read_config_32(port, destid, hopcount,
599 RIO_HOST_DID_LOCK_CSR, &result);
600 if ((result & 0xffff) != 0xffff) {
601 pr_debug("RIO: badness when releasing device lock %x:%x\n",
602 destid, hopcount);
603 return -EINVAL;
604 }
605
606 return 0;
607}
608
609/**
610 * rio_route_add_entry- Add a route entry to a switch routing table
611 * @rdev: RIO device
612 * @table: Routing table ID
613 * @route_destid: Destination ID to be routed
614 * @route_port: Port number to be routed
615 * @lock: lock switch device flag
616 *
617 * Calls the switch specific add_entry() method to add a route entry
618 * on a switch. The route table can be specified using the @table
619 * argument if a switch has per port routing tables or the normal
620 * use is to specific all tables (or the global table) by passing
621 * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
622 * on failure.
623 */
624static int
625rio_route_add_entry(struct rio_dev *rdev,
626 u16 table, u16 route_destid, u8 route_port, int lock)
627{
628 int rc;
629
630 if (lock) {
631 rc = rio_lock_device(rdev->net->hport, rdev->destid,
632 rdev->hopcount, 1000);
633 if (rc)
634 return rc;
635 }
636
637 rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid,
638 rdev->hopcount, table,
639 route_destid, route_port);
640 if (lock)
641 rio_unlock_device(rdev->net->hport, rdev->destid,
642 rdev->hopcount);
643
644 return rc;
645}
646
647/**
648 * rio_route_get_entry- Read a route entry in a switch routing table
649 * @rdev: RIO device
650 * @table: Routing table ID
651 * @route_destid: Destination ID to be routed
652 * @route_port: Pointer to read port number into
653 * @lock: lock switch device flag
654 *
655 * Calls the switch specific get_entry() method to read a route entry
656 * in a switch. The route table can be specified using the @table
657 * argument if a switch has per port routing tables or the normal
658 * use is to specific all tables (or the global table) by passing
659 * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
660 * on failure.
661 */
662static int
663rio_route_get_entry(struct rio_dev *rdev, u16 table,
664 u16 route_destid, u8 *route_port, int lock)
665{
666 int rc;
667
668 if (lock) {
669 rc = rio_lock_device(rdev->net->hport, rdev->destid,
670 rdev->hopcount, 1000);
671 if (rc)
672 return rc;
673 }
674
675 rc = rdev->rswitch->get_entry(rdev->net->hport, rdev->destid,
676 rdev->hopcount, table,
677 route_destid, route_port);
678 if (lock)
679 rio_unlock_device(rdev->net->hport, rdev->destid,
680 rdev->hopcount);
681
682 return rc;
683}
684
685/**
686 * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device 536 * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device
687 * @port: Master port to send transaction 537 * @port: Master port to send transaction
688 * @hopcount: Number of hops to the device 538 * @hopcount: Number of hops to the device
@@ -1094,12 +944,9 @@ static void rio_update_route_tables(struct rio_net *net)
1094 944
1095 sport = RIO_GET_PORT_NUM(swrdev->swpinfo); 945 sport = RIO_GET_PORT_NUM(swrdev->swpinfo);
1096 946
1097 if (rswitch->add_entry) { 947 rio_route_add_entry(swrdev, RIO_GLOBAL_TABLE,
1098 rio_route_add_entry(swrdev, 948 destid, sport, 0);
1099 RIO_GLOBAL_TABLE, destid, 949 rswitch->route_table[destid] = sport;
1100 sport, 0);
1101 rswitch->route_table[destid] = sport;
1102 }
1103 } 950 }
1104 } 951 }
1105 } 952 }
@@ -1115,8 +962,8 @@ static void rio_update_route_tables(struct rio_net *net)
1115static void rio_init_em(struct rio_dev *rdev) 962static void rio_init_em(struct rio_dev *rdev)
1116{ 963{
1117 if (rio_is_switch(rdev) && (rdev->em_efptr) && 964 if (rio_is_switch(rdev) && (rdev->em_efptr) &&
1118 (rdev->rswitch->em_init)) { 965 rdev->rswitch->ops && rdev->rswitch->ops->em_init) {
1119 rdev->rswitch->em_init(rdev); 966 rdev->rswitch->ops->em_init(rdev);
1120 } 967 }
1121} 968}
1122 969
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 66d4acd5e18f..864e52f193e1 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -257,8 +257,6 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
257 err |= device_create_file(&rdev->dev, &dev_attr_routes); 257 err |= device_create_file(&rdev->dev, &dev_attr_routes);
258 err |= device_create_file(&rdev->dev, &dev_attr_lnext); 258 err |= device_create_file(&rdev->dev, &dev_attr_lnext);
259 err |= device_create_file(&rdev->dev, &dev_attr_hopcount); 259 err |= device_create_file(&rdev->dev, &dev_attr_hopcount);
260 if (!err && rdev->rswitch->sw_sysfs)
261 err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE);
262 } 260 }
263 261
264 if (err) 262 if (err)
@@ -281,8 +279,6 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
281 device_remove_file(&rdev->dev, &dev_attr_routes); 279 device_remove_file(&rdev->dev, &dev_attr_routes);
282 device_remove_file(&rdev->dev, &dev_attr_lnext); 280 device_remove_file(&rdev->dev, &dev_attr_lnext);
283 device_remove_file(&rdev->dev, &dev_attr_hopcount); 281 device_remove_file(&rdev->dev, &dev_attr_hopcount);
284 if (rdev->rswitch->sw_sysfs)
285 rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
286 } 282 }
287} 283}
288 284
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index cb1c08996fbb..b17d5218005e 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -7,7 +7,6 @@
7 * 7 *
8 * Copyright 2009 Integrated Device Technology, Inc. 8 * Copyright 2009 Integrated Device Technology, Inc.
9 * Alex Bounine <alexandre.bounine@idt.com> 9 * Alex Bounine <alexandre.bounine@idt.com>
10 * - Added Port-Write/Error Management initialization and handling
11 * 10 *
12 * This program is free software; you can redistribute it and/or modify it 11 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the 12 * under the terms of the GNU General Public License as published by the
@@ -580,44 +579,6 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
580EXPORT_SYMBOL_GPL(rio_set_port_lockout); 579EXPORT_SYMBOL_GPL(rio_set_port_lockout);
581 580
582/** 581/**
583 * rio_switch_init - Sets switch operations for a particular vendor switch
584 * @rdev: RIO device
585 * @do_enum: Enumeration/Discovery mode flag
586 *
587 * Searches the RIO switch ops table for known switch types. If the vid
588 * and did match a switch table entry, then call switch initialization
589 * routine to setup switch-specific routines.
590 */
591void rio_switch_init(struct rio_dev *rdev, int do_enum)
592{
593 struct rio_switch_ops *cur = __start_rio_switch_ops;
594 struct rio_switch_ops *end = __end_rio_switch_ops;
595
596 while (cur < end) {
597 if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
598 pr_debug("RIO: calling init routine for %s\n",
599 rio_name(rdev));
600 cur->init_hook(rdev, do_enum);
601 break;
602 }
603 cur++;
604 }
605
606 if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
607 pr_debug("RIO: adding STD routing ops for %s\n",
608 rio_name(rdev));
609 rdev->rswitch->add_entry = rio_std_route_add_entry;
610 rdev->rswitch->get_entry = rio_std_route_get_entry;
611 rdev->rswitch->clr_table = rio_std_route_clr_table;
612 }
613
614 if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
615 printk(KERN_ERR "RIO: missing routing ops for %s\n",
616 rio_name(rdev));
617}
618EXPORT_SYMBOL_GPL(rio_switch_init);
619
620/**
621 * rio_enable_rx_tx_port - enable input receiver and output transmitter of 582 * rio_enable_rx_tx_port - enable input receiver and output transmitter of
622 * given port 583 * given port
623 * @port: Master port associated with the RIO network 584 * @port: Master port associated with the RIO network
@@ -970,8 +931,8 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
970 /* 931 /*
971 * Process the port-write notification from switch 932 * Process the port-write notification from switch
972 */ 933 */
973 if (rdev->rswitch->em_handle) 934 if (rdev->rswitch->ops && rdev->rswitch->ops->em_handle)
974 rdev->rswitch->em_handle(rdev, portnum); 935 rdev->rswitch->ops->em_handle(rdev, portnum);
975 936
976 rio_read_config_32(rdev, 937 rio_read_config_32(rdev,
977 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), 938 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
@@ -1207,8 +1168,9 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
1207 * @route_destid: destID entry in the RT 1168 * @route_destid: destID entry in the RT
1208 * @route_port: destination port for specified destID 1169 * @route_port: destination port for specified destID
1209 */ 1170 */
1210int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 1171static int
1211 u16 table, u16 route_destid, u8 route_port) 1172rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
1173 u16 table, u16 route_destid, u8 route_port)
1212{ 1174{
1213 if (table == RIO_GLOBAL_TABLE) { 1175 if (table == RIO_GLOBAL_TABLE) {
1214 rio_mport_write_config_32(mport, destid, hopcount, 1176 rio_mport_write_config_32(mport, destid, hopcount,
@@ -1234,8 +1196,9 @@ int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
1234 * @route_destid: destID entry in the RT 1196 * @route_destid: destID entry in the RT
1235 * @route_port: returned destination port for specified destID 1197 * @route_port: returned destination port for specified destID
1236 */ 1198 */
1237int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 1199static int
1238 u16 table, u16 route_destid, u8 *route_port) 1200rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
1201 u16 table, u16 route_destid, u8 *route_port)
1239{ 1202{
1240 u32 result; 1203 u32 result;
1241 1204
@@ -1259,8 +1222,9 @@ int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
1259 * @hopcount: Number of switch hops to the device 1222 * @hopcount: Number of switch hops to the device
1260 * @table: routing table ID (global or port-specific) 1223 * @table: routing table ID (global or port-specific)
1261 */ 1224 */
1262int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, 1225static int
1263 u16 table) 1226rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
1227 u16 table)
1264{ 1228{
1265 u32 max_destid = 0xff; 1229 u32 max_destid = 0xff;
1266 u32 i, pef, id_inc = 1, ext_cfg = 0; 1230 u32 i, pef, id_inc = 1, ext_cfg = 0;
@@ -1301,6 +1265,234 @@ int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
1301 return 0; 1265 return 0;
1302} 1266}
1303 1267
1268/**
1269 * rio_lock_device - Acquires host device lock for specified device
1270 * @port: Master port to send transaction
1271 * @destid: Destination ID for device/switch
1272 * @hopcount: Hopcount to reach switch
1273 * @wait_ms: Max wait time in msec (0 = no timeout)
1274 *
1275 * Attepts to acquire host device lock for specified device
1276 * Returns 0 if device lock acquired or EINVAL if timeout expires.
1277 */
1278int rio_lock_device(struct rio_mport *port, u16 destid,
1279 u8 hopcount, int wait_ms)
1280{
1281 u32 result;
1282 int tcnt = 0;
1283
1284 /* Attempt to acquire device lock */
1285 rio_mport_write_config_32(port, destid, hopcount,
1286 RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
1287 rio_mport_read_config_32(port, destid, hopcount,
1288 RIO_HOST_DID_LOCK_CSR, &result);
1289
1290 while (result != port->host_deviceid) {
1291 if (wait_ms != 0 && tcnt == wait_ms) {
1292 pr_debug("RIO: timeout when locking device %x:%x\n",
1293 destid, hopcount);
1294 return -EINVAL;
1295 }
1296
1297 /* Delay a bit */
1298 mdelay(1);
1299 tcnt++;
1300 /* Try to acquire device lock again */
1301 rio_mport_write_config_32(port, destid,
1302 hopcount,
1303 RIO_HOST_DID_LOCK_CSR,
1304 port->host_deviceid);
1305 rio_mport_read_config_32(port, destid,
1306 hopcount,
1307 RIO_HOST_DID_LOCK_CSR, &result);
1308 }
1309
1310 return 0;
1311}
1312EXPORT_SYMBOL_GPL(rio_lock_device);
1313
1314/**
1315 * rio_unlock_device - Releases host device lock for specified device
1316 * @port: Master port to send transaction
1317 * @destid: Destination ID for device/switch
1318 * @hopcount: Hopcount to reach switch
1319 *
1320 * Returns 0 if device lock released or EINVAL if fails.
1321 */
1322int rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
1323{
1324 u32 result;
1325
1326 /* Release device lock */
1327 rio_mport_write_config_32(port, destid,
1328 hopcount,
1329 RIO_HOST_DID_LOCK_CSR,
1330 port->host_deviceid);
1331 rio_mport_read_config_32(port, destid, hopcount,
1332 RIO_HOST_DID_LOCK_CSR, &result);
1333 if ((result & 0xffff) != 0xffff) {
1334 pr_debug("RIO: badness when releasing device lock %x:%x\n",
1335 destid, hopcount);
1336 return -EINVAL;
1337 }
1338
1339 return 0;
1340}
1341EXPORT_SYMBOL_GPL(rio_unlock_device);
1342
1343/**
1344 * rio_route_add_entry- Add a route entry to a switch routing table
1345 * @rdev: RIO device
1346 * @table: Routing table ID
1347 * @route_destid: Destination ID to be routed
1348 * @route_port: Port number to be routed
1349 * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
1350 *
1351 * If available calls the switch specific add_entry() method to add a route
1352 * entry into a switch routing table. Otherwise uses standard RT update method
1353 * as defined by RapidIO specification. A specific routing table can be selected
1354 * using the @table argument if a switch has per port routing tables or
1355 * the standard (or global) table may be used by passing
1356 * %RIO_GLOBAL_TABLE in @table.
1357 *
1358 * Returns %0 on success or %-EINVAL on failure.
1359 */
1360int rio_route_add_entry(struct rio_dev *rdev,
1361 u16 table, u16 route_destid, u8 route_port, int lock)
1362{
1363 int rc = -EINVAL;
1364 struct rio_switch_ops *ops = rdev->rswitch->ops;
1365
1366 if (lock) {
1367 rc = rio_lock_device(rdev->net->hport, rdev->destid,
1368 rdev->hopcount, 1000);
1369 if (rc)
1370 return rc;
1371 }
1372
1373 spin_lock(&rdev->rswitch->lock);
1374
1375 if (ops == NULL || ops->add_entry == NULL) {
1376 rc = rio_std_route_add_entry(rdev->net->hport, rdev->destid,
1377 rdev->hopcount, table,
1378 route_destid, route_port);
1379 } else if (try_module_get(ops->owner)) {
1380 rc = ops->add_entry(rdev->net->hport, rdev->destid,
1381 rdev->hopcount, table, route_destid,
1382 route_port);
1383 module_put(ops->owner);
1384 }
1385
1386 spin_unlock(&rdev->rswitch->lock);
1387
1388 if (lock)
1389 rio_unlock_device(rdev->net->hport, rdev->destid,
1390 rdev->hopcount);
1391
1392 return rc;
1393}
1394EXPORT_SYMBOL_GPL(rio_route_add_entry);
1395
1396/**
1397 * rio_route_get_entry- Read an entry from a switch routing table
1398 * @rdev: RIO device
1399 * @table: Routing table ID
1400 * @route_destid: Destination ID to be routed
1401 * @route_port: Pointer to read port number into
1402 * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
1403 *
1404 * If available calls the switch specific get_entry() method to fetch a route
1405 * entry from a switch routing table. Otherwise uses standard RT read method
1406 * as defined by RapidIO specification. A specific routing table can be selected
1407 * using the @table argument if a switch has per port routing tables or
1408 * the standard (or global) table may be used by passing
1409 * %RIO_GLOBAL_TABLE in @table.
1410 *
1411 * Returns %0 on success or %-EINVAL on failure.
1412 */
1413int rio_route_get_entry(struct rio_dev *rdev, u16 table,
1414 u16 route_destid, u8 *route_port, int lock)
1415{
1416 int rc = -EINVAL;
1417 struct rio_switch_ops *ops = rdev->rswitch->ops;
1418
1419 if (lock) {
1420 rc = rio_lock_device(rdev->net->hport, rdev->destid,
1421 rdev->hopcount, 1000);
1422 if (rc)
1423 return rc;
1424 }
1425
1426 spin_lock(&rdev->rswitch->lock);
1427
1428 if (ops == NULL || ops->get_entry == NULL) {
1429 rc = rio_std_route_get_entry(rdev->net->hport, rdev->destid,
1430 rdev->hopcount, table,
1431 route_destid, route_port);
1432 } else if (try_module_get(ops->owner)) {
1433 rc = ops->get_entry(rdev->net->hport, rdev->destid,
1434 rdev->hopcount, table, route_destid,
1435 route_port);
1436 module_put(ops->owner);
1437 }
1438
1439 spin_unlock(&rdev->rswitch->lock);
1440
1441 if (lock)
1442 rio_unlock_device(rdev->net->hport, rdev->destid,
1443 rdev->hopcount);
1444 return rc;
1445}
1446EXPORT_SYMBOL_GPL(rio_route_get_entry);
1447
1448/**
1449 * rio_route_clr_table - Clear a switch routing table
1450 * @rdev: RIO device
1451 * @table: Routing table ID
1452 * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
1453 *
1454 * If available calls the switch specific clr_table() method to clear a switch
1455 * routing table. Otherwise uses standard RT write method as defined by RapidIO
1456 * specification. A specific routing table can be selected using the @table
1457 * argument if a switch has per port routing tables or the standard (or global)
1458 * table may be used by passing %RIO_GLOBAL_TABLE in @table.
1459 *
1460 * Returns %0 on success or %-EINVAL on failure.
1461 */
1462int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock)
1463{
1464 int rc = -EINVAL;
1465 struct rio_switch_ops *ops = rdev->rswitch->ops;
1466
1467 if (lock) {
1468 rc = rio_lock_device(rdev->net->hport, rdev->destid,
1469 rdev->hopcount, 1000);
1470 if (rc)
1471 return rc;
1472 }
1473
1474 spin_lock(&rdev->rswitch->lock);
1475
1476 if (ops == NULL || ops->clr_table == NULL) {
1477 rc = rio_std_route_clr_table(rdev->net->hport, rdev->destid,
1478 rdev->hopcount, table);
1479 } else if (try_module_get(ops->owner)) {
1480 rc = ops->clr_table(rdev->net->hport, rdev->destid,
1481 rdev->hopcount, table);
1482
1483 module_put(ops->owner);
1484 }
1485
1486 spin_unlock(&rdev->rswitch->lock);
1487
1488 if (lock)
1489 rio_unlock_device(rdev->net->hport, rdev->destid,
1490 rdev->hopcount);
1491
1492 return rc;
1493}
1494EXPORT_SYMBOL_GPL(rio_route_clr_table);
1495
1304#ifdef CONFIG_RAPIDIO_DMA_ENGINE 1496#ifdef CONFIG_RAPIDIO_DMA_ENGINE
1305 1497
1306static bool rio_chan_filter(struct dma_chan *chan, void *arg) 1498static bool rio_chan_filter(struct dma_chan *chan, void *arg)
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index c14f864dea5c..d59587762c76 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -28,18 +28,17 @@ extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
28extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, 28extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid,
29 u8 hopcount); 29 u8 hopcount);
30extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); 30extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
31extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, 31extern int rio_lock_device(struct rio_mport *port, u16 destid,
32 u8 hopcount, u16 table, u16 route_destid, 32 u8 hopcount, int wait_ms);
33 u8 route_port); 33extern int rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount);
34extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, 34extern int rio_route_add_entry(struct rio_dev *rdev,
35 u8 hopcount, u16 table, u16 route_destid, 35 u16 table, u16 route_destid, u8 route_port, int lock);
36 u8 *route_port); 36extern int rio_route_get_entry(struct rio_dev *rdev, u16 table,
37extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, 37 u16 route_destid, u8 *route_port, int lock);
38 u8 hopcount, u16 table); 38extern int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock);
39extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); 39extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
40extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from); 40extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
41extern int rio_add_device(struct rio_dev *rdev); 41extern int rio_add_device(struct rio_dev *rdev);
42extern void rio_switch_init(struct rio_dev *rdev, int do_enum);
43extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid, 42extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
44 u8 hopcount, u8 port_num); 43 u8 hopcount, u8 port_num);
45extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops); 44extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
@@ -51,29 +50,5 @@ extern struct rio_mport *rio_find_mport(int mport_id);
51extern struct device_attribute rio_dev_attrs[]; 50extern struct device_attribute rio_dev_attrs[];
52extern struct bus_attribute rio_bus_attrs[]; 51extern struct bus_attribute rio_bus_attrs[];
53 52
54extern struct rio_switch_ops __start_rio_switch_ops[];
55extern struct rio_switch_ops __end_rio_switch_ops[];
56
57/* Helpers internal to the RIO core code */
58#define DECLARE_RIO_SWITCH_SECTION(section, name, vid, did, init_hook) \
59 static const struct rio_switch_ops __rio_switch_##name __used \
60 __section(section) = { vid, did, init_hook };
61
62/**
63 * DECLARE_RIO_SWITCH_INIT - Registers switch initialization routine
64 * @vid: RIO vendor ID
65 * @did: RIO device ID
66 * @init_hook: Callback that performs switch-specific initialization
67 *
68 * Manipulating switch route tables and error management in RIO
69 * is switch specific. This registers a switch by vendor and device ID with
70 * initialization callback for setting up switch operations and (if required)
71 * hardware initialization. A &struct rio_switch_ops is initialized with
72 * pointer to the init routine and placed into a RIO-specific kernel section.
73 */
74#define DECLARE_RIO_SWITCH_INIT(vid, did, init_hook) \
75 DECLARE_RIO_SWITCH_SECTION(.rio_switch_ops, vid##did, \
76 vid, did, init_hook)
77
78#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) 53#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
79#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) 54#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig
index 62d4a065230f..345841562f95 100644
--- a/drivers/rapidio/switches/Kconfig
+++ b/drivers/rapidio/switches/Kconfig
@@ -2,27 +2,23 @@
2# RapidIO switches configuration 2# RapidIO switches configuration
3# 3#
4config RAPIDIO_TSI57X 4config RAPIDIO_TSI57X
5 bool "IDT Tsi57x SRIO switches support" 5 tristate "IDT Tsi57x SRIO switches support"
6 depends on RAPIDIO
7 ---help--- 6 ---help---
8 Includes support for IDT Tsi57x family of serial RapidIO switches. 7 Includes support for IDT Tsi57x family of serial RapidIO switches.
9 8
10config RAPIDIO_CPS_XX 9config RAPIDIO_CPS_XX
11 bool "IDT CPS-xx SRIO switches support" 10 tristate "IDT CPS-xx SRIO switches support"
12 depends on RAPIDIO
13 ---help--- 11 ---help---
14 Includes support for IDT CPS-16/12/10/8 serial RapidIO switches. 12 Includes support for IDT CPS-16/12/10/8 serial RapidIO switches.
15 13
16config RAPIDIO_TSI568 14config RAPIDIO_TSI568
17 bool "Tsi568 SRIO switch support" 15 tristate "Tsi568 SRIO switch support"
18 depends on RAPIDIO
19 default n 16 default n
20 ---help--- 17 ---help---
21 Includes support for IDT Tsi568 serial RapidIO switch. 18 Includes support for IDT Tsi568 serial RapidIO switch.
22 19
23config RAPIDIO_CPS_GEN2 20config RAPIDIO_CPS_GEN2
24 bool "IDT CPS Gen.2 SRIO switch support" 21 tristate "IDT CPS Gen.2 SRIO switch support"
25 depends on RAPIDIO
26 default n 22 default n
27 ---help--- 23 ---help---
28 Includes support for ITD CPS Gen.2 serial RapidIO switches. 24 Includes support for ITD CPS Gen.2 serial RapidIO switches.
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c
index 809b7a3336ba..00a71ebb5cac 100644
--- a/drivers/rapidio/switches/idt_gen2.c
+++ b/drivers/rapidio/switches/idt_gen2.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/stat.h> 13#include <linux/stat.h>
14#include <linux/module.h>
14#include <linux/rio.h> 15#include <linux/rio.h>
15#include <linux/rio_drv.h> 16#include <linux/rio_drv.h>
16#include <linux/rio_ids.h> 17#include <linux/rio_ids.h>
@@ -387,12 +388,12 @@ idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf)
387 388
388static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL); 389static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL);
389 390
390static int idtg2_sysfs(struct rio_dev *rdev, int create) 391static int idtg2_sysfs(struct rio_dev *rdev, bool create)
391{ 392{
392 struct device *dev = &rdev->dev; 393 struct device *dev = &rdev->dev;
393 int err = 0; 394 int err = 0;
394 395
395 if (create == RIO_SW_SYSFS_CREATE) { 396 if (create) {
396 /* Initialize sysfs entries */ 397 /* Initialize sysfs entries */
397 err = device_create_file(dev, &dev_attr_errlog); 398 err = device_create_file(dev, &dev_attr_errlog);
398 if (err) 399 if (err)
@@ -403,29 +404,90 @@ static int idtg2_sysfs(struct rio_dev *rdev, int create)
403 return err; 404 return err;
404} 405}
405 406
406static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) 407static struct rio_switch_ops idtg2_switch_ops = {
408 .owner = THIS_MODULE,
409 .add_entry = idtg2_route_add_entry,
410 .get_entry = idtg2_route_get_entry,
411 .clr_table = idtg2_route_clr_table,
412 .set_domain = idtg2_set_domain,
413 .get_domain = idtg2_get_domain,
414 .em_init = idtg2_em_init,
415 .em_handle = idtg2_em_handler,
416};
417
418static int idtg2_probe(struct rio_dev *rdev, const struct rio_device_id *id)
407{ 419{
408 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 420 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
409 rdev->rswitch->add_entry = idtg2_route_add_entry; 421
410 rdev->rswitch->get_entry = idtg2_route_get_entry; 422 spin_lock(&rdev->rswitch->lock);
411 rdev->rswitch->clr_table = idtg2_route_clr_table; 423
412 rdev->rswitch->set_domain = idtg2_set_domain; 424 if (rdev->rswitch->ops) {
413 rdev->rswitch->get_domain = idtg2_get_domain; 425 spin_unlock(&rdev->rswitch->lock);
414 rdev->rswitch->em_init = idtg2_em_init; 426 return -EINVAL;
415 rdev->rswitch->em_handle = idtg2_em_handler; 427 }
416 rdev->rswitch->sw_sysfs = idtg2_sysfs; 428
417 429 rdev->rswitch->ops = &idtg2_switch_ops;
418 if (do_enum) { 430
431 if (rdev->do_enum) {
419 /* Ensure that default routing is disabled on startup */ 432 /* Ensure that default routing is disabled on startup */
420 rio_write_config_32(rdev, 433 rio_write_config_32(rdev,
421 RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE); 434 RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE);
422 } 435 }
423 436
437 /* Create device-specific sysfs attributes */
438 idtg2_sysfs(rdev, true);
439
440 spin_unlock(&rdev->rswitch->lock);
424 return 0; 441 return 0;
425} 442}
426 443
427DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); 444static void idtg2_remove(struct rio_dev *rdev)
428DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); 445{
429DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init); 446 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
430DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init); 447 spin_lock(&rdev->rswitch->lock);
431DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1432, idtg2_switch_init); 448 if (rdev->rswitch->ops != &idtg2_switch_ops) {
449 spin_unlock(&rdev->rswitch->lock);
450 return;
451 }
452 rdev->rswitch->ops = NULL;
453
454 /* Remove device-specific sysfs attributes */
455 idtg2_sysfs(rdev, false);
456
457 spin_unlock(&rdev->rswitch->lock);
458}
459
460static struct rio_device_id idtg2_id_table[] = {
461 {RIO_DEVICE(RIO_DID_IDTCPS1848, RIO_VID_IDT)},
462 {RIO_DEVICE(RIO_DID_IDTCPS1616, RIO_VID_IDT)},
463 {RIO_DEVICE(RIO_DID_IDTVPS1616, RIO_VID_IDT)},
464 {RIO_DEVICE(RIO_DID_IDTSPS1616, RIO_VID_IDT)},
465 {RIO_DEVICE(RIO_DID_IDTCPS1432, RIO_VID_IDT)},
466 { 0, } /* terminate list */
467};
468
469static struct rio_driver idtg2_driver = {
470 .name = "idt_gen2",
471 .id_table = idtg2_id_table,
472 .probe = idtg2_probe,
473 .remove = idtg2_remove,
474};
475
476static int __init idtg2_init(void)
477{
478 return rio_register_driver(&idtg2_driver);
479}
480
481static void __exit idtg2_exit(void)
482{
483 pr_debug("RIO: %s\n", __func__);
484 rio_unregister_driver(&idtg2_driver);
485 pr_debug("RIO: %s done\n", __func__);
486}
487
488device_initcall(idtg2_init);
489module_exit(idtg2_exit);
490
491MODULE_DESCRIPTION("IDT CPS Gen.2 Serial RapidIO switch family driver");
492MODULE_AUTHOR("Integrated Device Technology, Inc.");
493MODULE_LICENSE("GPL");
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c
index d06ee2d44b44..7fbb60d31796 100644
--- a/drivers/rapidio/switches/idtcps.c
+++ b/drivers/rapidio/switches/idtcps.c
@@ -13,6 +13,7 @@
13#include <linux/rio.h> 13#include <linux/rio.h>
14#include <linux/rio_drv.h> 14#include <linux/rio_drv.h>
15#include <linux/rio_ids.h> 15#include <linux/rio_ids.h>
16#include <linux/module.h>
16#include "../rio.h" 17#include "../rio.h"
17 18
18#define CPS_DEFAULT_ROUTE 0xde 19#define CPS_DEFAULT_ROUTE 0xde
@@ -118,18 +119,31 @@ idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
118 return 0; 119 return 0;
119} 120}
120 121
121static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) 122static struct rio_switch_ops idtcps_switch_ops = {
123 .owner = THIS_MODULE,
124 .add_entry = idtcps_route_add_entry,
125 .get_entry = idtcps_route_get_entry,
126 .clr_table = idtcps_route_clr_table,
127 .set_domain = idtcps_set_domain,
128 .get_domain = idtcps_get_domain,
129 .em_init = NULL,
130 .em_handle = NULL,
131};
132
133static int idtcps_probe(struct rio_dev *rdev, const struct rio_device_id *id)
122{ 134{
123 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 135 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
124 rdev->rswitch->add_entry = idtcps_route_add_entry; 136
125 rdev->rswitch->get_entry = idtcps_route_get_entry; 137 spin_lock(&rdev->rswitch->lock);
126 rdev->rswitch->clr_table = idtcps_route_clr_table; 138
127 rdev->rswitch->set_domain = idtcps_set_domain; 139 if (rdev->rswitch->ops) {
128 rdev->rswitch->get_domain = idtcps_get_domain; 140 spin_unlock(&rdev->rswitch->lock);
129 rdev->rswitch->em_init = NULL; 141 return -EINVAL;
130 rdev->rswitch->em_handle = NULL; 142 }
131 143
132 if (do_enum) { 144 rdev->rswitch->ops = &idtcps_switch_ops;
145
146 if (rdev->do_enum) {
133 /* set TVAL = ~50us */ 147 /* set TVAL = ~50us */
134 rio_write_config_32(rdev, 148 rio_write_config_32(rdev,
135 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); 149 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
@@ -138,12 +152,52 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum)
138 RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE); 152 RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
139 } 153 }
140 154
155 spin_unlock(&rdev->rswitch->lock);
141 return 0; 156 return 0;
142} 157}
143 158
144DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_switch_init); 159static void idtcps_remove(struct rio_dev *rdev)
145DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_switch_init); 160{
146DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_switch_init); 161 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
147DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_switch_init); 162 spin_lock(&rdev->rswitch->lock);
148DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_switch_init); 163 if (rdev->rswitch->ops != &idtcps_switch_ops) {
149DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_switch_init); 164 spin_unlock(&rdev->rswitch->lock);
165 return;
166 }
167 rdev->rswitch->ops = NULL;
168 spin_unlock(&rdev->rswitch->lock);
169}
170
171static struct rio_device_id idtcps_id_table[] = {
172 {RIO_DEVICE(RIO_DID_IDTCPS6Q, RIO_VID_IDT)},
173 {RIO_DEVICE(RIO_DID_IDTCPS8, RIO_VID_IDT)},
174 {RIO_DEVICE(RIO_DID_IDTCPS10Q, RIO_VID_IDT)},
175 {RIO_DEVICE(RIO_DID_IDTCPS12, RIO_VID_IDT)},
176 {RIO_DEVICE(RIO_DID_IDTCPS16, RIO_VID_IDT)},
177 {RIO_DEVICE(RIO_DID_IDT70K200, RIO_VID_IDT)},
178 { 0, } /* terminate list */
179};
180
181static struct rio_driver idtcps_driver = {
182 .name = "idtcps",
183 .id_table = idtcps_id_table,
184 .probe = idtcps_probe,
185 .remove = idtcps_remove,
186};
187
188static int __init idtcps_init(void)
189{
190 return rio_register_driver(&idtcps_driver);
191}
192
193static void __exit idtcps_exit(void)
194{
195 rio_unregister_driver(&idtcps_driver);
196}
197
198device_initcall(idtcps_init);
199module_exit(idtcps_exit);
200
201MODULE_DESCRIPTION("IDT CPS Gen.1 Serial RapidIO switch family driver");
202MODULE_AUTHOR("Integrated Device Technology, Inc.");
203MODULE_LICENSE("GPL");
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c
index 3994c00aa01f..8a43561b9d17 100644
--- a/drivers/rapidio/switches/tsi568.c
+++ b/drivers/rapidio/switches/tsi568.c
@@ -19,6 +19,7 @@
19#include <linux/rio_drv.h> 19#include <linux/rio_drv.h>
20#include <linux/rio_ids.h> 20#include <linux/rio_ids.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/module.h>
22#include "../rio.h" 23#include "../rio.h"
23 24
24/* Global (broadcast) route registers */ 25/* Global (broadcast) route registers */
@@ -129,18 +130,70 @@ tsi568_em_init(struct rio_dev *rdev)
129 return 0; 130 return 0;
130} 131}
131 132
132static int tsi568_switch_init(struct rio_dev *rdev, int do_enum) 133static struct rio_switch_ops tsi568_switch_ops = {
134 .owner = THIS_MODULE,
135 .add_entry = tsi568_route_add_entry,
136 .get_entry = tsi568_route_get_entry,
137 .clr_table = tsi568_route_clr_table,
138 .set_domain = NULL,
139 .get_domain = NULL,
140 .em_init = tsi568_em_init,
141 .em_handle = NULL,
142};
143
144static int tsi568_probe(struct rio_dev *rdev, const struct rio_device_id *id)
133{ 145{
134 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 146 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
135 rdev->rswitch->add_entry = tsi568_route_add_entry;
136 rdev->rswitch->get_entry = tsi568_route_get_entry;
137 rdev->rswitch->clr_table = tsi568_route_clr_table;
138 rdev->rswitch->set_domain = NULL;
139 rdev->rswitch->get_domain = NULL;
140 rdev->rswitch->em_init = tsi568_em_init;
141 rdev->rswitch->em_handle = NULL;
142 147
148 spin_lock(&rdev->rswitch->lock);
149
150 if (rdev->rswitch->ops) {
151 spin_unlock(&rdev->rswitch->lock);
152 return -EINVAL;
153 }
154
155 rdev->rswitch->ops = &tsi568_switch_ops;
156 spin_unlock(&rdev->rswitch->lock);
143 return 0; 157 return 0;
144} 158}
145 159
146DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_switch_init); 160static void tsi568_remove(struct rio_dev *rdev)
161{
162 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
163 spin_lock(&rdev->rswitch->lock);
164 if (rdev->rswitch->ops != &tsi568_switch_ops) {
165 spin_unlock(&rdev->rswitch->lock);
166 return;
167 }
168 rdev->rswitch->ops = NULL;
169 spin_unlock(&rdev->rswitch->lock);
170}
171
172static struct rio_device_id tsi568_id_table[] = {
173 {RIO_DEVICE(RIO_DID_TSI568, RIO_VID_TUNDRA)},
174 { 0, } /* terminate list */
175};
176
177static struct rio_driver tsi568_driver = {
178 .name = "tsi568",
179 .id_table = tsi568_id_table,
180 .probe = tsi568_probe,
181 .remove = tsi568_remove,
182};
183
184static int __init tsi568_init(void)
185{
186 return rio_register_driver(&tsi568_driver);
187}
188
189static void __exit tsi568_exit(void)
190{
191 rio_unregister_driver(&tsi568_driver);
192}
193
194device_initcall(tsi568_init);
195module_exit(tsi568_exit);
196
197MODULE_DESCRIPTION("IDT Tsi568 Serial RapidIO switch driver");
198MODULE_AUTHOR("Integrated Device Technology, Inc.");
199MODULE_LICENSE("GPL");
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c
index db8b8028988d..42c8b014fe15 100644
--- a/drivers/rapidio/switches/tsi57x.c
+++ b/drivers/rapidio/switches/tsi57x.c
@@ -19,6 +19,7 @@
19#include <linux/rio_drv.h> 19#include <linux/rio_drv.h>
20#include <linux/rio_ids.h> 20#include <linux/rio_ids.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/module.h>
22#include "../rio.h" 23#include "../rio.h"
23 24
24/* Global (broadcast) route registers */ 25/* Global (broadcast) route registers */
@@ -292,27 +293,79 @@ exit_es:
292 return 0; 293 return 0;
293} 294}
294 295
295static int tsi57x_switch_init(struct rio_dev *rdev, int do_enum) 296static struct rio_switch_ops tsi57x_switch_ops = {
297 .owner = THIS_MODULE,
298 .add_entry = tsi57x_route_add_entry,
299 .get_entry = tsi57x_route_get_entry,
300 .clr_table = tsi57x_route_clr_table,
301 .set_domain = tsi57x_set_domain,
302 .get_domain = tsi57x_get_domain,
303 .em_init = tsi57x_em_init,
304 .em_handle = tsi57x_em_handler,
305};
306
307static int tsi57x_probe(struct rio_dev *rdev, const struct rio_device_id *id)
296{ 308{
297 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 309 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
298 rdev->rswitch->add_entry = tsi57x_route_add_entry; 310
299 rdev->rswitch->get_entry = tsi57x_route_get_entry; 311 spin_lock(&rdev->rswitch->lock);
300 rdev->rswitch->clr_table = tsi57x_route_clr_table; 312
301 rdev->rswitch->set_domain = tsi57x_set_domain; 313 if (rdev->rswitch->ops) {
302 rdev->rswitch->get_domain = tsi57x_get_domain; 314 spin_unlock(&rdev->rswitch->lock);
303 rdev->rswitch->em_init = tsi57x_em_init; 315 return -EINVAL;
304 rdev->rswitch->em_handle = tsi57x_em_handler; 316 }
305 317 rdev->rswitch->ops = &tsi57x_switch_ops;
306 if (do_enum) { 318
319 if (rdev->do_enum) {
307 /* Ensure that default routing is disabled on startup */ 320 /* Ensure that default routing is disabled on startup */
308 rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT, 321 rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT,
309 RIO_INVALID_ROUTE); 322 RIO_INVALID_ROUTE);
310 } 323 }
311 324
325 spin_unlock(&rdev->rswitch->lock);
312 return 0; 326 return 0;
313} 327}
314 328
315DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_switch_init); 329static void tsi57x_remove(struct rio_dev *rdev)
316DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_switch_init); 330{
317DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_switch_init); 331 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
318DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_switch_init); 332 spin_lock(&rdev->rswitch->lock);
333 if (rdev->rswitch->ops != &tsi57x_switch_ops) {
334 spin_unlock(&rdev->rswitch->lock);
335 return;
336 }
337 rdev->rswitch->ops = NULL;
338 spin_unlock(&rdev->rswitch->lock);
339}
340
341static struct rio_device_id tsi57x_id_table[] = {
342 {RIO_DEVICE(RIO_DID_TSI572, RIO_VID_TUNDRA)},
343 {RIO_DEVICE(RIO_DID_TSI574, RIO_VID_TUNDRA)},
344 {RIO_DEVICE(RIO_DID_TSI577, RIO_VID_TUNDRA)},
345 {RIO_DEVICE(RIO_DID_TSI578, RIO_VID_TUNDRA)},
346 { 0, } /* terminate list */
347};
348
349static struct rio_driver tsi57x_driver = {
350 .name = "tsi57x",
351 .id_table = tsi57x_id_table,
352 .probe = tsi57x_probe,
353 .remove = tsi57x_remove,
354};
355
356static int __init tsi57x_init(void)
357{
358 return rio_register_driver(&tsi57x_driver);
359}
360
361static void __exit tsi57x_exit(void)
362{
363 rio_unregister_driver(&tsi57x_driver);
364}
365
366device_initcall(tsi57x_init);
367module_exit(tsi57x_exit);
368
369MODULE_DESCRIPTION("IDT Tsi57x Serial RapidIO switch family driver");
370MODULE_AUTHOR("Integrated Device Technology, Inc.");
371MODULE_LICENSE("GPL");
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4f2737208c42..c74d88baea60 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -275,13 +275,6 @@
275 VMLINUX_SYMBOL(__end_builtin_fw) = .; \ 275 VMLINUX_SYMBOL(__end_builtin_fw) = .; \
276 } \ 276 } \
277 \ 277 \
278 /* RapidIO route ops */ \
279 .rio_ops : AT(ADDR(.rio_ops) - LOAD_OFFSET) { \
280 VMLINUX_SYMBOL(__start_rio_switch_ops) = .; \
281 *(.rio_switch_ops) \
282 VMLINUX_SYMBOL(__end_rio_switch_ops) = .; \
283 } \
284 \
285 TRACEDATA \ 278 TRACEDATA \
286 \ 279 \
287 /* Kernel symbol table: Normal symbols */ \ 280 /* Kernel symbol table: Normal symbols */ \
diff --git a/include/linux/rio.h b/include/linux/rio.h
index 18e099342e6f..fcd492e7aff4 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -94,6 +94,23 @@ union rio_pw_msg;
94 * @switchid: Switch ID that is unique across a network 94 * @switchid: Switch ID that is unique across a network
95 * @route_table: Copy of switch routing table 95 * @route_table: Copy of switch routing table
96 * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0 96 * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0
97 * @ops: pointer to switch-specific operations
98 * @lock: lock to serialize operations updates
99 * @nextdev: Array of per-port pointers to the next attached device
100 */
101struct rio_switch {
102 struct list_head node;
103 u16 switchid;
104 u8 *route_table;
105 u32 port_ok;
106 struct rio_switch_ops *ops;
107 spinlock_t lock;
108 struct rio_dev *nextdev[0];
109};
110
111/**
112 * struct rio_switch_ops - Per-switch operations
113 * @owner: The module owner of this structure
97 * @add_entry: Callback for switch-specific route add function 114 * @add_entry: Callback for switch-specific route add function
98 * @get_entry: Callback for switch-specific route get function 115 * @get_entry: Callback for switch-specific route get function
99 * @clr_table: Callback for switch-specific clear route table function 116 * @clr_table: Callback for switch-specific clear route table function
@@ -101,14 +118,12 @@ union rio_pw_msg;
101 * @get_domain: Callback for switch-specific domain get function 118 * @get_domain: Callback for switch-specific domain get function
102 * @em_init: Callback for switch-specific error management init function 119 * @em_init: Callback for switch-specific error management init function
103 * @em_handle: Callback for switch-specific error management handler function 120 * @em_handle: Callback for switch-specific error management handler function
104 * @sw_sysfs: Callback that initializes switch-specific sysfs attributes 121 *
105 * @nextdev: Array of per-port pointers to the next attached device 122 * Defines the operations that are necessary to initialize/control
123 * a particular RIO switch device.
106 */ 124 */
107struct rio_switch { 125struct rio_switch_ops {
108 struct list_head node; 126 struct module *owner;
109 u16 switchid;
110 u8 *route_table;
111 u32 port_ok;
112 int (*add_entry) (struct rio_mport *mport, u16 destid, u8 hopcount, 127 int (*add_entry) (struct rio_mport *mport, u16 destid, u8 hopcount,
113 u16 table, u16 route_destid, u8 route_port); 128 u16 table, u16 route_destid, u8 route_port);
114 int (*get_entry) (struct rio_mport *mport, u16 destid, u8 hopcount, 129 int (*get_entry) (struct rio_mport *mport, u16 destid, u8 hopcount,
@@ -121,8 +136,6 @@ struct rio_switch {
121 u8 *sw_domain); 136 u8 *sw_domain);
122 int (*em_init) (struct rio_dev *dev); 137 int (*em_init) (struct rio_dev *dev);
123 int (*em_handle) (struct rio_dev *dev, u8 swport); 138 int (*em_handle) (struct rio_dev *dev, u8 swport);
124 int (*sw_sysfs) (struct rio_dev *dev, int create);
125 struct rio_dev *nextdev[0];
126}; 139};
127 140
128/** 141/**
@@ -130,6 +143,7 @@ struct rio_switch {
130 * @global_list: Node in list of all RIO devices 143 * @global_list: Node in list of all RIO devices
131 * @net_list: Node in list of RIO devices in a network 144 * @net_list: Node in list of RIO devices in a network
132 * @net: Network this device is a part of 145 * @net: Network this device is a part of
146 * @do_enum: Enumeration flag
133 * @did: Device ID 147 * @did: Device ID
134 * @vid: Vendor ID 148 * @vid: Vendor ID
135 * @device_rev: Device revision 149 * @device_rev: Device revision
@@ -158,6 +172,7 @@ struct rio_dev {
158 struct list_head global_list; /* node in list of all RIO devices */ 172 struct list_head global_list; /* node in list of all RIO devices */
159 struct list_head net_list; /* node in per net list */ 173 struct list_head net_list; /* node in per net list */
160 struct rio_net *net; /* RIO net this device resides in */ 174 struct rio_net *net; /* RIO net this device resides in */
175 bool do_enum;
161 u16 did; 176 u16 did;
162 u16 vid; 177 u16 vid;
163 u32 device_rev; 178 u32 device_rev;
@@ -297,10 +312,6 @@ struct rio_net {
297 struct rio_id_table destid_table; /* destID allocation table */ 312 struct rio_id_table destid_table; /* destID allocation table */
298}; 313};
299 314
300/* Definitions used by switch sysfs initialization callback */
301#define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */
302#define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */
303
304/* Low-level architecture-dependent routines */ 315/* Low-level architecture-dependent routines */
305 316
306/** 317/**
@@ -400,20 +411,6 @@ struct rio_device_id {
400 u16 asm_did, asm_vid; 411 u16 asm_did, asm_vid;
401}; 412};
402 413
403/**
404 * struct rio_switch_ops - Per-switch operations
405 * @vid: RIO vendor ID
406 * @did: RIO device ID
407 * @init_hook: Callback that performs switch device initialization
408 *
409 * Defines the operations that are necessary to initialize/control
410 * a particular RIO switch device.
411 */
412struct rio_switch_ops {
413 u16 vid, did;
414 int (*init_hook) (struct rio_dev *rdev, int do_enum);
415};
416
417union rio_pw_msg { 414union rio_pw_msg {
418 struct { 415 struct {
419 u32 comptag; /* Component Tag CSR */ 416 u32 comptag; /* Component Tag CSR */