aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.h1
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c16
-rw-r--r--drivers/rapidio/devices/tsi721.c24
-rw-r--r--drivers/rapidio/rio.c142
-rw-r--r--include/linux/rio.h2
-rw-r--r--include/linux/rio_drv.h9
7 files changed, 144 insertions, 51 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 385371acc0d0..f5bf38b94595 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -726,6 +726,7 @@ int fsl_rio_setup(struct platform_device *dev)
726 fsl_rio_inbound_mem_init(priv); 726 fsl_rio_inbound_mem_init(priv);
727 727
728 dbell->mport[i] = port; 728 dbell->mport[i] = port;
729 pw->mport[i] = port;
729 730
730 if (rio_register_mport(port)) { 731 if (rio_register_mport(port)) {
731 release_resource(&port->iores); 732 release_resource(&port->iores);
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h
index d53407a34f32..12dd18fd4795 100644
--- a/arch/powerpc/sysdev/fsl_rio.h
+++ b/arch/powerpc/sysdev/fsl_rio.h
@@ -97,6 +97,7 @@ struct fsl_rio_dbell {
97}; 97};
98 98
99struct fsl_rio_pw { 99struct fsl_rio_pw {
100 struct rio_mport *mport[MAX_PORT_NUM];
100 struct device *dev; 101 struct device *dev;
101 struct rio_pw_regs __iomem *pw_regs; 102 struct rio_pw_regs __iomem *pw_regs;
102 struct rio_port_write_msg port_write_msg; 103 struct rio_port_write_msg port_write_msg;
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index ffe0ee832768..c1826de4e749 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -481,14 +481,14 @@ pw_done:
481static void fsl_pw_dpc(struct work_struct *work) 481static void fsl_pw_dpc(struct work_struct *work)
482{ 482{
483 struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work); 483 struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work);
484 u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; 484 union rio_pw_msg msg_buffer;
485 int i;
485 486
486 /* 487 /*
487 * Process port-write messages 488 * Process port-write messages
488 */ 489 */
489 while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)msg_buffer, 490 while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)&msg_buffer,
490 RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) { 491 RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) {
491 /* Process one message */
492#ifdef DEBUG_PW 492#ifdef DEBUG_PW
493 { 493 {
494 u32 i; 494 u32 i;
@@ -496,15 +496,19 @@ static void fsl_pw_dpc(struct work_struct *work)
496 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) { 496 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
497 if ((i%4) == 0) 497 if ((i%4) == 0)
498 pr_debug("\n0x%02x: 0x%08x", i*4, 498 pr_debug("\n0x%02x: 0x%08x", i*4,
499 msg_buffer[i]); 499 msg_buffer.raw[i]);
500 else 500 else
501 pr_debug(" 0x%08x", msg_buffer[i]); 501 pr_debug(" 0x%08x", msg_buffer.raw[i]);
502 } 502 }
503 pr_debug("\n"); 503 pr_debug("\n");
504 } 504 }
505#endif 505#endif
506 /* Pass the port-write message to RIO core for processing */ 506 /* Pass the port-write message to RIO core for processing */
507 rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); 507 for (i = 0; i < MAX_PORT_NUM; i++) {
508 if (pw->mport[i])
509 rio_inb_pwrite_handler(pw->mport[i],
510 &msg_buffer);
511 }
508 } 512 }
509} 513}
510 514
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index db95d71ba4e9..5e1d52674e17 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -36,8 +36,6 @@
36 36
37#include "tsi721.h" 37#include "tsi721.h"
38 38
39#define DEBUG_PW /* Inbound Port-Write debugging */
40
41static void tsi721_omsg_handler(struct tsi721_device *priv, int ch); 39static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
42static void tsi721_imsg_handler(struct tsi721_device *priv, int ch); 40static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
43 41
@@ -282,30 +280,15 @@ static void tsi721_pw_dpc(struct work_struct *work)
282{ 280{
283 struct tsi721_device *priv = container_of(work, struct tsi721_device, 281 struct tsi721_device *priv = container_of(work, struct tsi721_device,
284 pw_work); 282 pw_work);
285 u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; /* Use full size PW message 283 union rio_pw_msg pwmsg;
286 buffer for RIO layer */
287 284
288 /* 285 /*
289 * Process port-write messages 286 * Process port-write messages
290 */ 287 */
291 while (kfifo_out_spinlocked(&priv->pw_fifo, (unsigned char *)msg_buffer, 288 while (kfifo_out_spinlocked(&priv->pw_fifo, (unsigned char *)&pwmsg,
292 TSI721_RIO_PW_MSG_SIZE, &priv->pw_fifo_lock)) { 289 TSI721_RIO_PW_MSG_SIZE, &priv->pw_fifo_lock)) {
293 /* Process one message */
294#ifdef DEBUG_PW
295 {
296 u32 i;
297 pr_debug("%s : Port-Write Message:", __func__);
298 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); ) {
299 pr_debug("0x%02x: %08x %08x %08x %08x", i*4,
300 msg_buffer[i], msg_buffer[i + 1],
301 msg_buffer[i + 2], msg_buffer[i + 3]);
302 i += 4;
303 }
304 pr_debug("\n");
305 }
306#endif
307 /* Pass the port-write message to RIO core for processing */ 290 /* Pass the port-write message to RIO core for processing */
308 rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); 291 rio_inb_pwrite_handler(&priv->mport, &pwmsg);
309 } 292 }
310} 293}
311 294
@@ -2702,6 +2685,7 @@ static void tsi721_remove(struct pci_dev *pdev)
2702 2685
2703 tsi721_disable_ints(priv); 2686 tsi721_disable_ints(priv);
2704 tsi721_free_irq(priv); 2687 tsi721_free_irq(priv);
2688 flush_scheduled_work();
2705 rio_unregister_mport(&priv->mport); 2689 rio_unregister_mport(&priv->mport);
2706 2690
2707 tsi721_unregister_dma(priv); 2691 tsi721_unregister_dma(priv);
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 673774bf6dd6..17973d3caa88 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -30,6 +30,20 @@
30 30
31#include "rio.h" 31#include "rio.h"
32 32
33/*
34 * struct rio_pwrite - RIO portwrite event
35 * @node: Node in list of doorbell events
36 * @pwcback: Doorbell event callback
37 * @context: Handler specific context to pass on event
38 */
39struct rio_pwrite {
40 struct list_head node;
41
42 int (*pwcback)(struct rio_mport *mport, void *context,
43 union rio_pw_msg *msg, int step);
44 void *context;
45};
46
33MODULE_DESCRIPTION("RapidIO Subsystem Core"); 47MODULE_DESCRIPTION("RapidIO Subsystem Core");
34MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>"); 48MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
35MODULE_AUTHOR("Alexandre Bounine <alexandre.bounine@idt.com>"); 49MODULE_AUTHOR("Alexandre Bounine <alexandre.bounine@idt.com>");
@@ -514,7 +528,71 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
514} 528}
515 529
516/** 530/**
517 * rio_request_inb_pwrite - request inbound port-write message service 531 * rio_add_mport_pw_handler - add port-write message handler into the list
532 * of mport specific pw handlers
533 * @mport: RIO master port to bind the portwrite callback
534 * @context: Handler specific context to pass on event
535 * @pwcback: Callback to execute when portwrite is received
536 *
537 * Returns 0 if the request has been satisfied.
538 */
539int rio_add_mport_pw_handler(struct rio_mport *mport, void *context,
540 int (*pwcback)(struct rio_mport *mport,
541 void *context, union rio_pw_msg *msg, int step))
542{
543 int rc = 0;
544 struct rio_pwrite *pwrite;
545
546 pwrite = kzalloc(sizeof(struct rio_pwrite), GFP_KERNEL);
547 if (!pwrite) {
548 rc = -ENOMEM;
549 goto out;
550 }
551
552 pwrite->pwcback = pwcback;
553 pwrite->context = context;
554 mutex_lock(&mport->lock);
555 list_add_tail(&pwrite->node, &mport->pwrites);
556 mutex_unlock(&mport->lock);
557out:
558 return rc;
559}
560EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler);
561
562/**
563 * rio_del_mport_pw_handler - remove port-write message handler from the list
564 * of mport specific pw handlers
565 * @mport: RIO master port to bind the portwrite callback
566 * @context: Registered handler specific context to pass on event
567 * @pwcback: Registered callback function
568 *
569 * Returns 0 if the request has been satisfied.
570 */
571int rio_del_mport_pw_handler(struct rio_mport *mport, void *context,
572 int (*pwcback)(struct rio_mport *mport,
573 void *context, union rio_pw_msg *msg, int step))
574{
575 int rc = -EINVAL;
576 struct rio_pwrite *pwrite;
577
578 mutex_lock(&mport->lock);
579 list_for_each_entry(pwrite, &mport->pwrites, node) {
580 if (pwrite->pwcback == pwcback && pwrite->context == context) {
581 list_del(&pwrite->node);
582 kfree(pwrite);
583 rc = 0;
584 break;
585 }
586 }
587 mutex_unlock(&mport->lock);
588
589 return rc;
590}
591EXPORT_SYMBOL_GPL(rio_del_mport_pw_handler);
592
593/**
594 * rio_request_inb_pwrite - request inbound port-write message service for
595 * specific RapidIO device
518 * @rdev: RIO device to which register inbound port-write callback routine 596 * @rdev: RIO device to which register inbound port-write callback routine
519 * @pwcback: Callback routine to execute when port-write is received 597 * @pwcback: Callback routine to execute when port-write is received
520 * 598 *
@@ -539,6 +617,7 @@ EXPORT_SYMBOL_GPL(rio_request_inb_pwrite);
539 617
540/** 618/**
541 * rio_release_inb_pwrite - release inbound port-write message service 619 * rio_release_inb_pwrite - release inbound port-write message service
620 * associated with specific RapidIO device
542 * @rdev: RIO device which registered for inbound port-write callback 621 * @rdev: RIO device which registered for inbound port-write callback
543 * 622 *
544 * Removes callback from the rio_dev structure. Returns 0 if the request 623 * Removes callback from the rio_dev structure. Returns 0 if the request
@@ -1002,52 +1081,66 @@ rd_err:
1002} 1081}
1003 1082
1004/** 1083/**
1005 * rio_inb_pwrite_handler - process inbound port-write message 1084 * rio_inb_pwrite_handler - inbound port-write message handler
1085 * @mport: mport device associated with port-write
1006 * @pw_msg: pointer to inbound port-write message 1086 * @pw_msg: pointer to inbound port-write message
1007 * 1087 *
1008 * Processes an inbound port-write message. Returns 0 if the request 1088 * Processes an inbound port-write message. Returns 0 if the request
1009 * has been satisfied. 1089 * has been satisfied.
1010 */ 1090 */
1011int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) 1091int rio_inb_pwrite_handler(struct rio_mport *mport, union rio_pw_msg *pw_msg)
1012{ 1092{
1013 struct rio_dev *rdev; 1093 struct rio_dev *rdev;
1014 u32 err_status, em_perrdet, em_ltlerrdet; 1094 u32 err_status, em_perrdet, em_ltlerrdet;
1015 int rc, portnum; 1095 int rc, portnum;
1016 1096 struct rio_pwrite *pwrite;
1017 rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL);
1018 if (rdev == NULL) {
1019 /* Device removed or enumeration error */
1020 pr_debug("RIO: %s No matching device for CTag 0x%08x\n",
1021 __func__, pw_msg->em.comptag);
1022 return -EIO;
1023 }
1024
1025 pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
1026 1097
1027#ifdef DEBUG_PW 1098#ifdef DEBUG_PW
1028 { 1099 {
1029 u32 i; 1100 u32 i;
1030 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { 1101
1102 pr_debug("%s: PW to mport_%d:\n", __func__, mport->id);
1103 for (i = 0; i < RIO_PW_MSG_SIZE / sizeof(u32); i = i + 4) {
1031 pr_debug("0x%02x: %08x %08x %08x %08x\n", 1104 pr_debug("0x%02x: %08x %08x %08x %08x\n",
1032 i*4, pw_msg->raw[i], pw_msg->raw[i + 1], 1105 i * 4, pw_msg->raw[i], pw_msg->raw[i + 1],
1033 pw_msg->raw[i + 2], pw_msg->raw[i + 3]); 1106 pw_msg->raw[i + 2], pw_msg->raw[i + 3]);
1034 i += 4; 1107 }
1035 }
1036 } 1108 }
1037#endif 1109#endif
1038 1110
1039 /* Call an external service function (if such is registered 1111 rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL);
1040 * for this device). This may be the service for endpoints that send 1112 if (rdev) {
1041 * device-specific port-write messages. End-point messages expected 1113 pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
1042 * to be handled completely by EP specific device driver. 1114 } else {
1115 pr_debug("RIO: %s No matching device for CTag 0x%08x\n",
1116 __func__, pw_msg->em.comptag);
1117 }
1118
1119 /* Call a device-specific handler (if it is registered for the device).
1120 * This may be the service for endpoints that send device-specific
1121 * port-write messages. End-point messages expected to be handled
1122 * completely by EP specific device driver.
1043 * For switches rc==0 signals that no standard processing required. 1123 * For switches rc==0 signals that no standard processing required.
1044 */ 1124 */
1045 if (rdev->pwcback != NULL) { 1125 if (rdev && rdev->pwcback) {
1046 rc = rdev->pwcback(rdev, pw_msg, 0); 1126 rc = rdev->pwcback(rdev, pw_msg, 0);
1047 if (rc == 0) 1127 if (rc == 0)
1048 return 0; 1128 return 0;
1049 } 1129 }
1050 1130
1131 mutex_lock(&mport->lock);
1132 list_for_each_entry(pwrite, &mport->pwrites, node)
1133 pwrite->pwcback(mport, pwrite->context, pw_msg, 0);
1134 mutex_unlock(&mport->lock);
1135
1136 if (!rdev)
1137 return 0;
1138
1139 /*
1140 * FIXME: The code below stays as it was before for now until we decide
1141 * how to do default PW handling in combination with per-mport callbacks
1142 */
1143
1051 portnum = pw_msg->em.is_port & 0xFF; 1144 portnum = pw_msg->em.is_port & 0xFF;
1052 1145
1053 /* Check if device and route to it are functional: 1146 /* Check if device and route to it are functional:
@@ -2060,6 +2153,7 @@ int rio_mport_initialize(struct rio_mport *mport)
2060 mport->nscan = NULL; 2153 mport->nscan = NULL;
2061 mutex_init(&mport->lock); 2154 mutex_init(&mport->lock);
2062 mport->pwe_refcnt = 0; 2155 mport->pwe_refcnt = 0;
2156 INIT_LIST_HEAD(&mport->pwrites);
2063 2157
2064 return 0; 2158 return 0;
2065} 2159}
diff --git a/include/linux/rio.h b/include/linux/rio.h
index cb3c47543bb0..44f3da512c15 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -245,6 +245,7 @@ enum rio_phy_type {
245/** 245/**
246 * struct rio_mport - RIO master port info 246 * struct rio_mport - RIO master port info
247 * @dbells: List of doorbell events 247 * @dbells: List of doorbell events
248 * @pwrites: List of portwrite events
248 * @node: Node in global list of master ports 249 * @node: Node in global list of master ports
249 * @nnode: Node in network list of master ports 250 * @nnode: Node in network list of master ports
250 * @net: RIO net this mport is attached to 251 * @net: RIO net this mport is attached to
@@ -270,6 +271,7 @@ enum rio_phy_type {
270 */ 271 */
271struct rio_mport { 272struct rio_mport {
272 struct list_head dbells; /* list of doorbell events */ 273 struct list_head dbells; /* list of doorbell events */
274 struct list_head pwrites; /* list of portwrite events */
273 struct list_head node; /* node in global list of ports */ 275 struct list_head node; /* node in global list of ports */
274 struct list_head nnode; /* node in net list of ports */ 276 struct list_head nnode; /* node in net list of ports */
275 struct rio_net *net; /* RIO net this mport is attached to */ 277 struct rio_net *net; /* RIO net this mport is attached to */
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
index 9fb2bcd0a987..5dff9a4cb675 100644
--- a/include/linux/rio_drv.h
+++ b/include/linux/rio_drv.h
@@ -374,7 +374,14 @@ extern void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart);
374extern int rio_request_inb_pwrite(struct rio_dev *, 374extern int rio_request_inb_pwrite(struct rio_dev *,
375 int (*)(struct rio_dev *, union rio_pw_msg*, int)); 375 int (*)(struct rio_dev *, union rio_pw_msg*, int));
376extern int rio_release_inb_pwrite(struct rio_dev *); 376extern int rio_release_inb_pwrite(struct rio_dev *);
377extern int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg); 377extern int rio_add_mport_pw_handler(struct rio_mport *mport, void *dev_id,
378 int (*pwcback)(struct rio_mport *mport, void *dev_id,
379 union rio_pw_msg *msg, int step));
380extern int rio_del_mport_pw_handler(struct rio_mport *mport, void *dev_id,
381 int (*pwcback)(struct rio_mport *mport, void *dev_id,
382 union rio_pw_msg *msg, int step));
383extern int rio_inb_pwrite_handler(struct rio_mport *mport,
384 union rio_pw_msg *pw_msg);
378extern void rio_pw_enable(struct rio_mport *mport, int enable); 385extern void rio_pw_enable(struct rio_mport *mport, int enable);
379 386
380/* LDM support */ 387/* LDM support */