aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2010-05-26 17:43:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 12:12:50 -0400
commite5cabeb3d60f9cd3e3950aff071319ae0e2d08d8 (patch)
treee866f1a9076608630a40f21f0a50c073dedb0e57 /drivers/rapidio
parent818a04a0bb93643d57dd8935815de2ff307b58a3 (diff)
rapidio: add Port-Write handling for EM
Add RapidIO Port-Write message handling in the context of Error Management Extensions Specification Rev.1.3. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Tested-by: 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> 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.c166
-rw-r--r--drivers/rapidio/rio.c328
-rw-r--r--drivers/rapidio/rio.h30
-rw-r--r--drivers/rapidio/switches/tsi568.c24
-rw-r--r--drivers/rapidio/switches/tsi57x.c153
5 files changed, 665 insertions, 36 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index cbf0d5f4fba8..74633cc6b2eb 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -4,6 +4,10 @@
4 * Copyright 2005 MontaVista Software, Inc. 4 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org> 5 * Matt Porter <mporter@kernel.crashing.org>
6 * 6 *
7 * Copyright 2009 Integrated Device Technology, Inc.
8 * Alex Bounine <alexandre.bounine@idt.com>
9 * - Added Port-Write/Error Management initialization and handling
10 *
7 * 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
8 * 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
9 * Free Software Foundation; either version 2 of the License, or (at your 13 * Free Software Foundation; either version 2 of the License, or (at your
@@ -31,15 +35,16 @@
31LIST_HEAD(rio_devices); 35LIST_HEAD(rio_devices);
32static LIST_HEAD(rio_switches); 36static LIST_HEAD(rio_switches);
33 37
34#define RIO_ENUM_CMPL_MAGIC 0xdeadbeef
35
36static void rio_enum_timeout(unsigned long); 38static void rio_enum_timeout(unsigned long);
37 39
40static void rio_init_em(struct rio_dev *rdev);
41
38DEFINE_SPINLOCK(rio_global_list_lock); 42DEFINE_SPINLOCK(rio_global_list_lock);
39 43
40static int next_destid = 0; 44static int next_destid = 0;
41static int next_switchid = 0; 45static int next_switchid = 0;
42static int next_net = 0; 46static int next_net = 0;
47static int next_comptag;
43 48
44static struct timer_list rio_enum_timer = 49static struct timer_list rio_enum_timer =
45TIMER_INITIALIZER(rio_enum_timeout, 0, 0); 50TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
@@ -52,13 +57,6 @@ static int rio_mport_phys_table[] = {
52 -1, 57 -1,
53}; 58};
54 59
55static int rio_sport_phys_table[] = {
56 RIO_EFB_PAR_EP_FREE_ID,
57 RIO_EFB_SER_EP_FREE_ID,
58 RIO_EFB_SER_EP_FREC_ID,
59 -1,
60};
61
62/** 60/**
63 * rio_get_device_id - Get the base/extended device id for a device 61 * rio_get_device_id - Get the base/extended device id for a device
64 * @port: RIO master port 62 * @port: RIO master port
@@ -119,12 +117,26 @@ static int rio_clear_locks(struct rio_mport *port)
119 u32 result; 117 u32 result;
120 int ret = 0; 118 int ret = 0;
121 119
122 /* Write component tag CSR magic complete value */ 120 /* Assign component tag to all devices */
123 rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, 121 next_comptag = 1;
124 RIO_ENUM_CMPL_MAGIC); 122 rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++);
125 list_for_each_entry(rdev, &rio_devices, global_list) 123
126 rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, 124 list_for_each_entry(rdev, &rio_devices, global_list) {
127 RIO_ENUM_CMPL_MAGIC); 125 /* Mark device as discovered */
126 rio_read_config_32(rdev,
127 rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
128 &result);
129 rio_write_config_32(rdev,
130 rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
131 result | RIO_PORT_GEN_DISCOVERED);
132
133 rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag);
134 rdev->comp_tag = next_comptag++;
135 if (next_comptag >= 0x10000) {
136 pr_err("RIO: Component Tag Counter Overflow\n");
137 break;
138 }
139 }
128 140
129 /* Release host device id locks */ 141 /* Release host device id locks */
130 rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 142 rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
@@ -267,6 +279,30 @@ static void rio_route_set_ops(struct rio_dev *rdev)
267} 279}
268 280
269/** 281/**
282 * rio_em_set_ops- Sets Error Managment operations for a particular vendor switch
283 * @rdev: RIO device
284 *
285 * Searches the RIO EM ops table for known switch types. If the vid
286 * and did match a switch table entry, then set the em_init() and
287 * em_handle() ops to the table entry values.
288 */
289static void rio_em_set_ops(struct rio_dev *rdev)
290{
291 struct rio_em_ops *cur = __start_rio_em_ops;
292 struct rio_em_ops *end = __end_rio_em_ops;
293
294 while (cur < end) {
295 if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
296 pr_debug("RIO: adding EM ops for %s\n", rio_name(rdev));
297 rdev->rswitch->em_init = cur->init_hook;
298 rdev->rswitch->em_handle = cur->handler_hook;
299 break;
300 }
301 cur++;
302 }
303}
304
305/**
270 * rio_add_device- Adds a RIO device to the device model 306 * rio_add_device- Adds a RIO device to the device model
271 * @rdev: RIO device 307 * @rdev: RIO device
272 * 308 *
@@ -336,8 +372,14 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
336 rdev->asm_rev = result >> 16; 372 rdev->asm_rev = result >> 16;
337 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, 373 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
338 &rdev->pef); 374 &rdev->pef);
339 if (rdev->pef & RIO_PEF_EXT_FEATURES) 375 if (rdev->pef & RIO_PEF_EXT_FEATURES) {
340 rdev->efptr = result & 0xffff; 376 rdev->efptr = result & 0xffff;
377 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
378 hopcount);
379
380 rdev->em_efptr = rio_mport_get_feature(port, 0, destid,
381 hopcount, RIO_EFB_ERR_MGMNT);
382 }
341 383
342 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 384 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
343 &rdev->src_ops); 385 &rdev->src_ops);
@@ -366,6 +408,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
366 rswitch->switchid = next_switchid; 408 rswitch->switchid = next_switchid;
367 rswitch->hopcount = hopcount; 409 rswitch->hopcount = hopcount;
368 rswitch->destid = destid; 410 rswitch->destid = destid;
411 rswitch->port_ok = 0;
369 rswitch->route_table = kzalloc(sizeof(u8)* 412 rswitch->route_table = kzalloc(sizeof(u8)*
370 RIO_MAX_ROUTE_ENTRIES(port->sys_size), 413 RIO_MAX_ROUTE_ENTRIES(port->sys_size),
371 GFP_KERNEL); 414 GFP_KERNEL);
@@ -379,6 +422,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
379 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 422 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
380 rdev->rswitch->switchid); 423 rdev->rswitch->switchid);
381 rio_route_set_ops(rdev); 424 rio_route_set_ops(rdev);
425 rio_em_set_ops(rdev);
382 426
383 if (do_enum && rdev->rswitch->clr_table) 427 if (do_enum && rdev->rswitch->clr_table)
384 rdev->rswitch->clr_table(port, destid, hopcount, 428 rdev->rswitch->clr_table(port, destid, hopcount,
@@ -429,23 +473,29 @@ cleanup:
429 * 473 *
430 * Reads the port error status CSR for a particular switch port to 474 * Reads the port error status CSR for a particular switch port to
431 * determine if the port has an active link. Returns 475 * determine if the port has an active link. Returns
432 * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is 476 * %RIO_PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
433 * inactive. 477 * inactive.
434 */ 478 */
435static int 479static int
436rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) 480rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
437{ 481{
438 u32 result; 482 u32 result = 0;
439 u32 ext_ftr_ptr; 483 u32 ext_ftr_ptr;
440 484
441 int *entry = rio_sport_phys_table; 485 ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, 0);
442
443 do {
444 if ((ext_ftr_ptr =
445 rio_mport_get_feature(port, 0, destid, hopcount, *entry)))
446 486
487 while (ext_ftr_ptr) {
488 rio_mport_read_config_32(port, destid, hopcount,
489 ext_ftr_ptr, &result);
490 result = RIO_GET_BLOCK_ID(result);
491 if ((result == RIO_EFB_SER_EP_FREE_ID) ||
492 (result == RIO_EFB_SER_EP_FREE_ID_V13P) ||
493 (result == RIO_EFB_SER_EP_FREC_ID))
447 break; 494 break;
448 } while (*++entry >= 0); 495
496 ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount,
497 ext_ftr_ptr);
498 }
449 499
450 if (ext_ftr_ptr) 500 if (ext_ftr_ptr)
451 rio_mport_read_config_32(port, destid, hopcount, 501 rio_mport_read_config_32(port, destid, hopcount,
@@ -453,7 +503,7 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
453 RIO_PORT_N_ERR_STS_CSR(sport), 503 RIO_PORT_N_ERR_STS_CSR(sport),
454 &result); 504 &result);
455 505
456 return (result & PORT_N_ERR_STS_PORT_OK); 506 return result & RIO_PORT_N_ERR_STS_PORT_OK;
457} 507}
458 508
459/** 509/**
@@ -762,8 +812,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
762 rio_name(rdev), rdev->vid, rdev->did, num_ports); 812 rio_name(rdev), rdev->vid, rdev->did, num_ports);
763 sw_destid = next_destid; 813 sw_destid = next_destid;
764 for (port_num = 0; port_num < num_ports; port_num++) { 814 for (port_num = 0; port_num < num_ports; port_num++) {
765 if (sw_inport == port_num) 815 if (sw_inport == port_num) {
816 rdev->rswitch->port_ok |= (1 << port_num);
766 continue; 817 continue;
818 }
767 819
768 cur_destid = next_destid; 820 cur_destid = next_destid;
769 821
@@ -773,6 +825,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
773 pr_debug( 825 pr_debug(
774 "RIO: scanning device on port %d\n", 826 "RIO: scanning device on port %d\n",
775 port_num); 827 port_num);
828 rdev->rswitch->port_ok |= (1 << port_num);
776 rio_route_add_entry(port, rdev->rswitch, 829 rio_route_add_entry(port, rdev->rswitch,
777 RIO_GLOBAL_TABLE, 830 RIO_GLOBAL_TABLE,
778 RIO_ANY_DESTID(port->sys_size), 831 RIO_ANY_DESTID(port->sys_size),
@@ -797,9 +850,28 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
797 port_num; 850 port_num;
798 } 851 }
799 } 852 }
853 } else {
854 /* If switch supports Error Management,
855 * set PORT_LOCKOUT bit for unused port
856 */
857 if (rdev->em_efptr)
858 rio_set_port_lockout(rdev, port_num, 1);
859
860 rdev->rswitch->port_ok &= ~(1 << port_num);
800 } 861 }
801 } 862 }
802 863
864 /* Direct Port-write messages to the enumeratiing host */
865 if ((rdev->src_ops & RIO_SRC_OPS_PORT_WRITE) &&
866 (rdev->em_efptr)) {
867 rio_write_config_32(rdev,
868 rdev->em_efptr + RIO_EM_PW_TGT_DEVID,
869 (port->host_deviceid << 16) |
870 (port->sys_size << 15));
871 }
872
873 rio_init_em(rdev);
874
803 /* Check for empty switch */ 875 /* Check for empty switch */
804 if (next_destid == sw_destid) { 876 if (next_destid == sw_destid) {
805 next_destid++; 877 next_destid++;
@@ -819,21 +891,16 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
819 * rio_enum_complete- Tests if enumeration of a network is complete 891 * rio_enum_complete- Tests if enumeration of a network is complete
820 * @port: Master port to send transaction 892 * @port: Master port to send transaction
821 * 893 *
822 * Tests the Component Tag CSR for presence of the magic enumeration 894 * Tests the Component Tag CSR for non-zero value (enumeration
823 * complete flag. Return %1 if enumeration is complete or %0 if 895 * complete flag). Return %1 if enumeration is complete or %0 if
824 * enumeration is incomplete. 896 * enumeration is incomplete.
825 */ 897 */
826static int rio_enum_complete(struct rio_mport *port) 898static int rio_enum_complete(struct rio_mport *port)
827{ 899{
828 u32 tag_csr; 900 u32 tag_csr;
829 int ret = 0;
830 901
831 rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); 902 rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
832 903 return (tag_csr & 0xffff) ? 1 : 0;
833 if (tag_csr == RIO_ENUM_CMPL_MAGIC)
834 ret = 1;
835
836 return ret;
837} 904}
838 905
839/** 906/**
@@ -915,7 +982,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
915 * 982 *
916 * Reads the port error status CSR for the master port to 983 * Reads the port error status CSR for the master port to
917 * determine if the port has an active link. Returns 984 * determine if the port has an active link. Returns
918 * %PORT_N_ERR_STS_PORT_OK if the master port is active 985 * %RIO_PORT_N_ERR_STS_PORT_OK if the master port is active
919 * or %0 if it is inactive. 986 * or %0 if it is inactive.
920 */ 987 */
921static int rio_mport_is_active(struct rio_mport *port) 988static int rio_mport_is_active(struct rio_mport *port)
@@ -936,7 +1003,7 @@ static int rio_mport_is_active(struct rio_mport *port)
936 RIO_PORT_N_ERR_STS_CSR(port->index), 1003 RIO_PORT_N_ERR_STS_CSR(port->index),
937 &result); 1004 &result);
938 1005
939 return (result & PORT_N_ERR_STS_PORT_OK); 1006 return result & RIO_PORT_N_ERR_STS_PORT_OK;
940} 1007}
941 1008
942/** 1009/**
@@ -1008,6 +1075,32 @@ static void rio_update_route_tables(struct rio_mport *port)
1008} 1075}
1009 1076
1010/** 1077/**
1078 * rio_init_em - Initializes RIO Error Management (for switches)
1079 * @port: Master port associated with the RIO network
1080 *
1081 * For each enumerated switch, call device-specific error management
1082 * initialization routine (if supplied by the switch driver).
1083 */
1084static void rio_init_em(struct rio_dev *rdev)
1085{
1086 if (rio_is_switch(rdev) && (rdev->em_efptr) &&
1087 (rdev->rswitch->em_init)) {
1088 rdev->rswitch->em_init(rdev);
1089 }
1090}
1091
1092/**
1093 * rio_pw_enable - Enables/disables port-write handling by a master port
1094 * @port: Master port associated with port-write handling
1095 * @enable: 1=enable, 0=disable
1096 */
1097static void rio_pw_enable(struct rio_mport *port, int enable)
1098{
1099 if (port->ops->pwenable)
1100 port->ops->pwenable(port, enable);
1101}
1102
1103/**
1011 * rio_enum_mport- Start enumeration through a master port 1104 * rio_enum_mport- Start enumeration through a master port
1012 * @mport: Master port to send transactions 1105 * @mport: Master port to send transactions
1013 * 1106 *
@@ -1050,6 +1143,7 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1050 } 1143 }
1051 rio_update_route_tables(mport); 1144 rio_update_route_tables(mport);
1052 rio_clear_locks(mport); 1145 rio_clear_locks(mport);
1146 rio_pw_enable(mport, 1);
1053 } else { 1147 } else {
1054 printk(KERN_INFO "RIO: master port %d link inactive\n", 1148 printk(KERN_INFO "RIO: master port %d link inactive\n",
1055 mport->id); 1149 mport->id);
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 67a379216959..8fa732e46bf6 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -5,6 +5,10 @@
5 * Copyright 2005 MontaVista Software, Inc. 5 * Copyright 2005 MontaVista Software, Inc.
6 * Matt Porter <mporter@kernel.crashing.org> 6 * Matt Porter <mporter@kernel.crashing.org>
7 * 7 *
8 * Copyright 2009 Integrated Device Technology, Inc.
9 * Alex Bounine <alexandre.bounine@idt.com>
10 * - Added Port-Write/Error Management initialization and handling
11 *
8 * This program is free software; you can redistribute it and/or modify it 12 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 13 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your 14 * Free Software Foundation; either version 2 of the License, or (at your
@@ -333,6 +337,329 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
333} 337}
334 338
335/** 339/**
340 * rio_request_inb_pwrite - request inbound port-write message service
341 * @mport: RIO device to which register inbound port-write callback routine
342 * @pwcback: Callback routine to execute when port-write is received
343 *
344 * Binds a port-write callback function to the RapidIO device.
345 * Returns 0 if the request has been satisfied.
346 */
347int rio_request_inb_pwrite(struct rio_dev *rdev,
348 int (*pwcback)(struct rio_dev *rdev, union rio_pw_msg *msg, int step))
349{
350 int rc = 0;
351
352 spin_lock(&rio_global_list_lock);
353 if (rdev->pwcback != NULL)
354 rc = -ENOMEM;
355 else
356 rdev->pwcback = pwcback;
357
358 spin_unlock(&rio_global_list_lock);
359 return rc;
360}
361EXPORT_SYMBOL_GPL(rio_request_inb_pwrite);
362
363/**
364 * rio_release_inb_pwrite - release inbound port-write message service
365 * @rdev: RIO device which registered for inbound port-write callback
366 *
367 * Removes callback from the rio_dev structure. Returns 0 if the request
368 * has been satisfied.
369 */
370int rio_release_inb_pwrite(struct rio_dev *rdev)
371{
372 int rc = -ENOMEM;
373
374 spin_lock(&rio_global_list_lock);
375 if (rdev->pwcback) {
376 rdev->pwcback = NULL;
377 rc = 0;
378 }
379
380 spin_unlock(&rio_global_list_lock);
381 return rc;
382}
383EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
384
385/**
386 * rio_mport_get_physefb - Helper function that returns register offset
387 * for Physical Layer Extended Features Block.
388 * @rdev: RIO device
389 */
390u32
391rio_mport_get_physefb(struct rio_mport *port, int local,
392 u16 destid, u8 hopcount)
393{
394 u32 ext_ftr_ptr;
395 u32 ftr_header;
396
397 ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0);
398
399 while (ext_ftr_ptr) {
400 if (local)
401 rio_local_read_config_32(port, ext_ftr_ptr,
402 &ftr_header);
403 else
404 rio_mport_read_config_32(port, destid, hopcount,
405 ext_ftr_ptr, &ftr_header);
406
407 ftr_header = RIO_GET_BLOCK_ID(ftr_header);
408 switch (ftr_header) {
409
410 case RIO_EFB_SER_EP_ID_V13P:
411 case RIO_EFB_SER_EP_REC_ID_V13P:
412 case RIO_EFB_SER_EP_FREE_ID_V13P:
413 case RIO_EFB_SER_EP_ID:
414 case RIO_EFB_SER_EP_REC_ID:
415 case RIO_EFB_SER_EP_FREE_ID:
416 case RIO_EFB_SER_EP_FREC_ID:
417
418 return ext_ftr_ptr;
419
420 default:
421 break;
422 }
423
424 ext_ftr_ptr = rio_mport_get_efb(port, local, destid,
425 hopcount, ext_ftr_ptr);
426 }
427
428 return ext_ftr_ptr;
429}
430
431/**
432 * rio_get_comptag - Begin or continue searching for a RIO device by component tag
433 * @comp_tag: RIO component tad to match
434 * @from: Previous RIO device found in search, or %NULL for new search
435 *
436 * Iterates through the list of known RIO devices. If a RIO device is
437 * found with a matching @comp_tag, a pointer to its device
438 * structure is returned. Otherwise, %NULL is returned. A new search
439 * is initiated by passing %NULL to the @from argument. Otherwise, if
440 * @from is not %NULL, searches continue from next device on the global
441 * list.
442 */
443static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
444{
445 struct list_head *n;
446 struct rio_dev *rdev;
447
448 WARN_ON(in_interrupt());
449 spin_lock(&rio_global_list_lock);
450 n = from ? from->global_list.next : rio_devices.next;
451
452 while (n && (n != &rio_devices)) {
453 rdev = rio_dev_g(n);
454 if (rdev->comp_tag == comp_tag)
455 goto exit;
456 n = n->next;
457 }
458 rdev = NULL;
459exit:
460 spin_unlock(&rio_global_list_lock);
461 return rdev;
462}
463
464/**
465 * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
466 * @rdev: Pointer to RIO device control structure
467 * @pnum: Switch port number to set LOCKOUT bit
468 * @lock: Operation : set (=1) or clear (=0)
469 */
470int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
471{
472 u8 hopcount = 0xff;
473 u16 destid = rdev->destid;
474 u32 regval;
475
476 if (rdev->rswitch) {
477 destid = rdev->rswitch->destid;
478 hopcount = rdev->rswitch->hopcount;
479 }
480
481 rio_mport_read_config_32(rdev->net->hport, destid, hopcount,
482 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
483 &regval);
484 if (lock)
485 regval |= RIO_PORT_N_CTL_LOCKOUT;
486 else
487 regval &= ~RIO_PORT_N_CTL_LOCKOUT;
488
489 rio_mport_write_config_32(rdev->net->hport, destid, hopcount,
490 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
491 regval);
492 return 0;
493}
494
495/**
496 * rio_inb_pwrite_handler - process inbound port-write message
497 * @pw_msg: pointer to inbound port-write message
498 *
499 * Processes an inbound port-write message. Returns 0 if the request
500 * has been satisfied.
501 */
502int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
503{
504 struct rio_dev *rdev;
505 struct rio_mport *mport;
506 u8 hopcount;
507 u16 destid;
508 u32 err_status;
509 int rc, portnum;
510
511 rdev = rio_get_comptag(pw_msg->em.comptag, NULL);
512 if (rdev == NULL) {
513 /* Someting bad here (probably enumeration error) */
514 pr_err("RIO: %s No matching device for CTag 0x%08x\n",
515 __func__, pw_msg->em.comptag);
516 return -EIO;
517 }
518
519 pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
520
521#ifdef DEBUG_PW
522 {
523 u32 i;
524 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) {
525 pr_debug("0x%02x: %08x %08x %08x %08x",
526 i*4, pw_msg->raw[i], pw_msg->raw[i + 1],
527 pw_msg->raw[i + 2], pw_msg->raw[i + 3]);
528 i += 4;
529 }
530 pr_debug("\n");
531 }
532#endif
533
534 /* Call an external service function (if such is registered
535 * for this device). This may be the service for endpoints that send
536 * device-specific port-write messages. End-point messages expected
537 * to be handled completely by EP specific device driver.
538 * For switches rc==0 signals that no standard processing required.
539 */
540 if (rdev->pwcback != NULL) {
541 rc = rdev->pwcback(rdev, pw_msg, 0);
542 if (rc == 0)
543 return 0;
544 }
545
546 /* For End-point devices processing stops here */
547 if (!(rdev->pef & RIO_PEF_SWITCH))
548 return 0;
549
550 if (rdev->phys_efptr == 0) {
551 pr_err("RIO_PW: Bad switch initialization for %s\n",
552 rio_name(rdev));
553 return 0;
554 }
555
556 mport = rdev->net->hport;
557 destid = rdev->rswitch->destid;
558 hopcount = rdev->rswitch->hopcount;
559
560 /*
561 * Process the port-write notification from switch
562 */
563
564 portnum = pw_msg->em.is_port & 0xFF;
565
566 if (rdev->rswitch->em_handle)
567 rdev->rswitch->em_handle(rdev, portnum);
568
569 rio_mport_read_config_32(mport, destid, hopcount,
570 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
571 &err_status);
572 pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status);
573
574 if (pw_msg->em.errdetect) {
575 pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
576 portnum, pw_msg->em.errdetect);
577 /* Clear EM Port N Error Detect CSR */
578 rio_mport_write_config_32(mport, destid, hopcount,
579 rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
580 }
581
582 if (pw_msg->em.ltlerrdet) {
583 pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n",
584 pw_msg->em.ltlerrdet);
585 /* Clear EM L/T Layer Error Detect CSR */
586 rio_mport_write_config_32(mport, destid, hopcount,
587 rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
588 }
589
590 /* Clear Port Errors */
591 rio_mport_write_config_32(mport, destid, hopcount,
592 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
593 err_status & RIO_PORT_N_ERR_STS_CLR_MASK);
594
595 if (rdev->rswitch->port_ok & (1 << portnum)) {
596 if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) {
597 rdev->rswitch->port_ok &= ~(1 << portnum);
598 rio_set_port_lockout(rdev, portnum, 1);
599
600 rio_mport_write_config_32(mport, destid, hopcount,
601 rdev->phys_efptr +
602 RIO_PORT_N_ACK_STS_CSR(portnum),
603 RIO_PORT_N_ACK_CLEAR);
604
605 /* Schedule Extraction Service */
606 pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n",
607 rio_name(rdev), portnum);
608 }
609 } else {
610 if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
611 rdev->rswitch->port_ok |= (1 << portnum);
612 rio_set_port_lockout(rdev, portnum, 0);
613
614 /* Schedule Insertion Service */
615 pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
616 rio_name(rdev), portnum);
617 }
618 }
619
620 /* Clear Port-Write Pending bit */
621 rio_mport_write_config_32(mport, destid, hopcount,
622 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
623 RIO_PORT_N_ERR_STS_PW_PEND);
624
625 return 0;
626}
627EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler);
628
629/**
630 * rio_mport_get_efb - get pointer to next extended features block
631 * @port: Master port to issue transaction
632 * @local: Indicate a local master port or remote device access
633 * @destid: Destination ID of the device
634 * @hopcount: Number of switch hops to the device
635 * @from: Offset of current Extended Feature block header (if 0 starts
636 * from ExtFeaturePtr)
637 */
638u32
639rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
640 u8 hopcount, u32 from)
641{
642 u32 reg_val;
643
644 if (from == 0) {
645 if (local)
646 rio_local_read_config_32(port, RIO_ASM_INFO_CAR,
647 &reg_val);
648 else
649 rio_mport_read_config_32(port, destid, hopcount,
650 RIO_ASM_INFO_CAR, &reg_val);
651 return reg_val & RIO_EXT_FTR_PTR_MASK;
652 } else {
653 if (local)
654 rio_local_read_config_32(port, from, &reg_val);
655 else
656 rio_mport_read_config_32(port, destid, hopcount,
657 from, &reg_val);
658 return RIO_GET_BLOCK_ID(reg_val);
659 }
660}
661
662/**
336 * rio_mport_get_feature - query for devices' extended features 663 * rio_mport_get_feature - query for devices' extended features
337 * @port: Master port to issue transaction 664 * @port: Master port to issue transaction
338 * @local: Indicate a local master port or remote device access 665 * @local: Indicate a local master port or remote device access
@@ -472,6 +799,7 @@ int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
472 RIO_STD_RTE_CONF_PORT_SEL_CSR, 799 RIO_STD_RTE_CONF_PORT_SEL_CSR,
473 (u32)route_port); 800 (u32)route_port);
474 } 801 }
802
475 udelay(10); 803 udelay(10);
476 return 0; 804 return 0;
477} 805}
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index b53c5ec276a5..2f628ce1a1c1 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -18,6 +18,10 @@
18 18
19extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, 19extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
20 u8 hopcount, int ftr); 20 u8 hopcount, int ftr);
21extern u32 rio_mport_get_physefb(struct rio_mport *port, int local,
22 u16 destid, u8 hopcount);
23extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
24 u8 hopcount, u32 from);
21extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); 25extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
22extern int rio_enum_mport(struct rio_mport *mport); 26extern int rio_enum_mport(struct rio_mport *mport);
23extern int rio_disc_mport(struct rio_mport *mport); 27extern int rio_disc_mport(struct rio_mport *mport);
@@ -29,6 +33,7 @@ extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
29 u8 *route_port); 33 u8 *route_port);
30extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, 34extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
31 u8 hopcount, u16 table); 35 u8 hopcount, u16 table);
36extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
32 37
33/* Structures internal to the RIO core code */ 38/* Structures internal to the RIO core code */
34extern struct device_attribute rio_dev_attrs[]; 39extern struct device_attribute rio_dev_attrs[];
@@ -61,3 +66,28 @@ extern struct rio_route_ops __end_rio_route_ops[];
61 66
62#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) 67#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
63#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) 68#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
69
70/*
71 * RapidIO Error Management
72 */
73extern struct rio_em_ops __start_rio_em_ops[];
74extern struct rio_em_ops __end_rio_em_ops[];
75
76/* Helpers internal to the RIO core code */
77#define DECLARE_RIO_EM_SECTION(section, name, vid, did, init_hook, em_hook) \
78 static const struct rio_em_ops __rio_em_##name __used \
79 __section(section) = { vid, did, init_hook, em_hook };
80
81/**
82 * DECLARE_RIO_EM_OPS - Registers switch EM operations
83 * @vid: RIO vendor ID
84 * @did: RIO device ID
85 * @init_hook: Callback that initializes device specific EM
86 * @em_hook: Callback that handles device specific EM
87 *
88 * A &struct rio_em_ops is initialized with the ops and placed into a
89 * RIO-specific kernel section.
90 */
91#define DECLARE_RIO_EM_OPS(vid, did, init_hook, em_hook) \
92 DECLARE_RIO_EM_SECTION(.rio_em_ops, vid##did, \
93 vid, did, init_hook, em_hook)
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c
index bce9112ff0d9..905cf9cb09cc 100644
--- a/drivers/rapidio/switches/tsi568.c
+++ b/drivers/rapidio/switches/tsi568.c
@@ -25,6 +25,9 @@
25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) 25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) 26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
27 27
28#define TSI568_SP_MODE_BC 0x10004
29#define TSI568_SP_MODE_PW_DIS 0x08000000
30
28static int 31static int
29tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 32tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
30 u16 table, u16 route_destid, u8 route_port) 33 u16 table, u16 route_destid, u8 route_port)
@@ -104,3 +107,24 @@ tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
104} 107}
105 108
106DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_route_add_entry, tsi568_route_get_entry, tsi568_route_clr_table); 109DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_route_add_entry, tsi568_route_get_entry, tsi568_route_clr_table);
110
111static int
112tsi568_em_init(struct rio_dev *rdev)
113{
114 struct rio_mport *mport = rdev->net->hport;
115 u16 destid = rdev->rswitch->destid;
116 u8 hopcount = rdev->rswitch->hopcount;
117 u32 regval;
118
119 pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount);
120
121 /* Make sure that Port-Writes are disabled (for all ports) */
122 rio_mport_read_config_32(mport, destid, hopcount,
123 TSI568_SP_MODE_BC, &regval);
124 rio_mport_write_config_32(mport, destid, hopcount,
125 TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS);
126
127 return 0;
128}
129
130DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_em_init, NULL);
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c
index 5ad7880787c9..23040b92ea76 100644
--- a/drivers/rapidio/switches/tsi57x.c
+++ b/drivers/rapidio/switches/tsi57x.c
@@ -25,6 +25,14 @@
25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) 25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) 26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
27 27
28#define TSI578_SP_MODE(n) (0x11004 + n*0x100)
29#define TSI578_SP_MODE_PW_DIS 0x08000000
30
31#define TSI578_SP_CTL_INDEP(n) (0x13004 + n*0x100)
32#define TSI578_SP_LUT_PEINF(n) (0x13010 + n*0x100)
33#define TSI578_SP_CS_TX(n) (0x13014 + n*0x100)
34#define TSI578_SP_INT_STATUS(n) (0x13018 + n*0x100)
35
28static int 36static int
29tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 37tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
30 u16 table, u16 route_destid, u8 route_port) 38 u16 table, u16 route_destid, u8 route_port)
@@ -104,3 +112,148 @@ DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_route_add_entry, ts
104DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table); 112DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
105DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table); 113DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
106DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table); 114DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
115
116static int
117tsi57x_em_init(struct rio_dev *rdev)
118{
119 struct rio_mport *mport = rdev->net->hport;
120 u16 destid = rdev->rswitch->destid;
121 u8 hopcount = rdev->rswitch->hopcount;
122 u32 regval;
123 int portnum;
124
125 pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount);
126
127 for (portnum = 0; portnum < 16; portnum++) {
128 /* Make sure that Port-Writes are enabled (for all ports) */
129 rio_mport_read_config_32(mport, destid, hopcount,
130 TSI578_SP_MODE(portnum), &regval);
131 rio_mport_write_config_32(mport, destid, hopcount,
132 TSI578_SP_MODE(portnum),
133 regval & ~TSI578_SP_MODE_PW_DIS);
134
135 /* Clear all pending interrupts */
136 rio_mport_read_config_32(mport, destid, hopcount,
137 rdev->phys_efptr +
138 RIO_PORT_N_ERR_STS_CSR(portnum),
139 &regval);
140 rio_mport_write_config_32(mport, destid, hopcount,
141 rdev->phys_efptr +
142 RIO_PORT_N_ERR_STS_CSR(portnum),
143 regval & 0x07120214);
144
145 rio_mport_read_config_32(mport, destid, hopcount,
146 TSI578_SP_INT_STATUS(portnum), &regval);
147 rio_mport_write_config_32(mport, destid, hopcount,
148 TSI578_SP_INT_STATUS(portnum),
149 regval & 0x000700bd);
150
151 /* Enable all interrupts to allow ports to send a port-write */
152 rio_mport_read_config_32(mport, destid, hopcount,
153 TSI578_SP_CTL_INDEP(portnum), &regval);
154 rio_mport_write_config_32(mport, destid, hopcount,
155 TSI578_SP_CTL_INDEP(portnum),
156 regval | 0x000b0000);
157
158 /* Skip next (odd) port if the current port is in x4 mode */
159 rio_mport_read_config_32(mport, destid, hopcount,
160 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
161 &regval);
162 if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4)
163 portnum++;
164 }
165
166 return 0;
167}
168
169static int
170tsi57x_em_handler(struct rio_dev *rdev, u8 portnum)
171{
172 struct rio_mport *mport = rdev->net->hport;
173 u16 destid = rdev->rswitch->destid;
174 u8 hopcount = rdev->rswitch->hopcount;
175 u32 intstat, err_status;
176 int sendcount, checkcount;
177 u8 route_port;
178 u32 regval;
179
180 rio_mport_read_config_32(mport, destid, hopcount,
181 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
182 &err_status);
183
184 if ((err_status & RIO_PORT_N_ERR_STS_PORT_OK) &&
185 (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES |
186 RIO_PORT_N_ERR_STS_PW_INP_ES))) {
187 /* Remove any queued packets by locking/unlocking port */
188 rio_mport_read_config_32(mport, destid, hopcount,
189 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
190 &regval);
191 if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) {
192 rio_mport_write_config_32(mport, destid, hopcount,
193 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
194 regval | RIO_PORT_N_CTL_LOCKOUT);
195 udelay(50);
196 rio_mport_write_config_32(mport, destid, hopcount,
197 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
198 regval);
199 }
200
201 /* Read from link maintenance response register to clear
202 * valid bit
203 */
204 rio_mport_read_config_32(mport, destid, hopcount,
205 rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum),
206 &regval);
207
208 /* Send a Packet-Not-Accepted/Link-Request-Input-Status control
209 * symbol to recover from IES/OES
210 */
211 sendcount = 3;
212 while (sendcount) {
213 rio_mport_write_config_32(mport, destid, hopcount,
214 TSI578_SP_CS_TX(portnum), 0x40fc8000);
215 checkcount = 3;
216 while (checkcount--) {
217 udelay(50);
218 rio_mport_read_config_32(
219 mport, destid, hopcount,
220 rdev->phys_efptr +
221 RIO_PORT_N_MNT_RSP_CSR(portnum),
222 &regval);
223 if (regval & RIO_PORT_N_MNT_RSP_RVAL)
224 goto exit_es;
225 }
226
227 sendcount--;
228 }
229 }
230
231exit_es:
232 /* Clear implementation specific error status bits */
233 rio_mport_read_config_32(mport, destid, hopcount,
234 TSI578_SP_INT_STATUS(portnum), &intstat);
235 pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n",
236 destid, hopcount, portnum, intstat);
237
238 if (intstat & 0x10000) {
239 rio_mport_read_config_32(mport, destid, hopcount,
240 TSI578_SP_LUT_PEINF(portnum), &regval);
241 regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24);
242 route_port = rdev->rswitch->route_table[regval];
243 pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n",
244 rio_name(rdev), portnum, regval);
245 tsi57x_route_add_entry(mport, destid, hopcount,
246 RIO_GLOBAL_TABLE, regval, route_port);
247 }
248
249 rio_mport_write_config_32(mport, destid, hopcount,
250 TSI578_SP_INT_STATUS(portnum),
251 intstat & 0x000700bd);
252
253 return 0;
254}
255
256DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_em_init, tsi57x_em_handler);
257DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_em_init, tsi57x_em_handler);
258DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_em_init, tsi57x_em_handler);
259DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_em_init, tsi57x_em_handler);