forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rapidio: add global inbound port write interfaces
Add new Port Write handler registration interfaces that attach PW handlers to local mport device objects. This is different from old interface that attaches PW callback to individual RapidIO device. The new interfaces are intended for use for common event handling (e.g. hot-plug notifications) while the old interface is available for individual device drivers. This patch is based on patch proposed by Andre van Herk but preserves existing per-device interface and adds lock protection for list handling. Signed-off-by: Alexandre Bounine <[email protected]> Cc: Matt Porter <[email protected]> Cc: Aurelien Jacquiot <[email protected]> Cc: Andre van Herk <[email protected]> Cc: Stephen Rothwell <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
7 changed files
with
144 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,20 @@ | |
|
||
#include "rio.h" | ||
|
||
/* | ||
* struct rio_pwrite - RIO portwrite event | ||
* @node: Node in list of doorbell events | ||
* @pwcback: Doorbell event callback | ||
* @context: Handler specific context to pass on event | ||
*/ | ||
struct rio_pwrite { | ||
struct list_head node; | ||
|
||
int (*pwcback)(struct rio_mport *mport, void *context, | ||
union rio_pw_msg *msg, int step); | ||
void *context; | ||
}; | ||
|
||
MODULE_DESCRIPTION("RapidIO Subsystem Core"); | ||
MODULE_AUTHOR("Matt Porter <[email protected]>"); | ||
MODULE_AUTHOR("Alexandre Bounine <[email protected]>"); | ||
|
@@ -514,7 +528,71 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) | |
} | ||
|
||
/** | ||
* rio_request_inb_pwrite - request inbound port-write message service | ||
* rio_add_mport_pw_handler - add port-write message handler into the list | ||
* of mport specific pw handlers | ||
* @mport: RIO master port to bind the portwrite callback | ||
* @context: Handler specific context to pass on event | ||
* @pwcback: Callback to execute when portwrite is received | ||
* | ||
* Returns 0 if the request has been satisfied. | ||
*/ | ||
int rio_add_mport_pw_handler(struct rio_mport *mport, void *context, | ||
int (*pwcback)(struct rio_mport *mport, | ||
void *context, union rio_pw_msg *msg, int step)) | ||
{ | ||
int rc = 0; | ||
struct rio_pwrite *pwrite; | ||
|
||
pwrite = kzalloc(sizeof(struct rio_pwrite), GFP_KERNEL); | ||
if (!pwrite) { | ||
rc = -ENOMEM; | ||
goto out; | ||
} | ||
|
||
pwrite->pwcback = pwcback; | ||
pwrite->context = context; | ||
mutex_lock(&mport->lock); | ||
list_add_tail(&pwrite->node, &mport->pwrites); | ||
mutex_unlock(&mport->lock); | ||
out: | ||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler); | ||
|
||
/** | ||
* rio_del_mport_pw_handler - remove port-write message handler from the list | ||
* of mport specific pw handlers | ||
* @mport: RIO master port to bind the portwrite callback | ||
* @context: Registered handler specific context to pass on event | ||
* @pwcback: Registered callback function | ||
* | ||
* Returns 0 if the request has been satisfied. | ||
*/ | ||
int rio_del_mport_pw_handler(struct rio_mport *mport, void *context, | ||
int (*pwcback)(struct rio_mport *mport, | ||
void *context, union rio_pw_msg *msg, int step)) | ||
{ | ||
int rc = -EINVAL; | ||
struct rio_pwrite *pwrite; | ||
|
||
mutex_lock(&mport->lock); | ||
list_for_each_entry(pwrite, &mport->pwrites, node) { | ||
if (pwrite->pwcback == pwcback && pwrite->context == context) { | ||
list_del(&pwrite->node); | ||
kfree(pwrite); | ||
rc = 0; | ||
break; | ||
} | ||
} | ||
mutex_unlock(&mport->lock); | ||
|
||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(rio_del_mport_pw_handler); | ||
|
||
/** | ||
* rio_request_inb_pwrite - request inbound port-write message service for | ||
* specific RapidIO device | ||
* @rdev: RIO device to which register inbound port-write callback routine | ||
* @pwcback: Callback routine to execute when port-write is received | ||
* | ||
|
@@ -539,6 +617,7 @@ EXPORT_SYMBOL_GPL(rio_request_inb_pwrite); | |
|
||
/** | ||
* rio_release_inb_pwrite - release inbound port-write message service | ||
* associated with specific RapidIO device | ||
* @rdev: RIO device which registered for inbound port-write callback | ||
* | ||
* Removes callback from the rio_dev structure. Returns 0 if the request | ||
|
@@ -1002,52 +1081,66 @@ static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | |
} | ||
|
||
/** | ||
* rio_inb_pwrite_handler - process inbound port-write message | ||
* rio_inb_pwrite_handler - inbound port-write message handler | ||
* @mport: mport device associated with port-write | ||
* @pw_msg: pointer to inbound port-write message | ||
* | ||
* Processes an inbound port-write message. Returns 0 if the request | ||
* has been satisfied. | ||
*/ | ||
int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | ||
int rio_inb_pwrite_handler(struct rio_mport *mport, union rio_pw_msg *pw_msg) | ||
{ | ||
struct rio_dev *rdev; | ||
u32 err_status, em_perrdet, em_ltlerrdet; | ||
int rc, portnum; | ||
|
||
rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL); | ||
if (rdev == NULL) { | ||
/* Device removed or enumeration error */ | ||
pr_debug("RIO: %s No matching device for CTag 0x%08x\n", | ||
__func__, pw_msg->em.comptag); | ||
return -EIO; | ||
} | ||
|
||
pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev)); | ||
struct rio_pwrite *pwrite; | ||
|
||
#ifdef DEBUG_PW | ||
{ | ||
u32 i; | ||
for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { | ||
u32 i; | ||
|
||
pr_debug("%s: PW to mport_%d:\n", __func__, mport->id); | ||
for (i = 0; i < RIO_PW_MSG_SIZE / sizeof(u32); i = i + 4) { | ||
pr_debug("0x%02x: %08x %08x %08x %08x\n", | ||
i*4, pw_msg->raw[i], pw_msg->raw[i + 1], | ||
pw_msg->raw[i + 2], pw_msg->raw[i + 3]); | ||
i += 4; | ||
} | ||
i * 4, pw_msg->raw[i], pw_msg->raw[i + 1], | ||
pw_msg->raw[i + 2], pw_msg->raw[i + 3]); | ||
} | ||
} | ||
#endif | ||
|
||
/* Call an external service function (if such is registered | ||
* for this device). This may be the service for endpoints that send | ||
* device-specific port-write messages. End-point messages expected | ||
* to be handled completely by EP specific device driver. | ||
rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL); | ||
if (rdev) { | ||
pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev)); | ||
} else { | ||
pr_debug("RIO: %s No matching device for CTag 0x%08x\n", | ||
__func__, pw_msg->em.comptag); | ||
} | ||
|
||
/* Call a device-specific handler (if it is registered for the device). | ||
* This may be the service for endpoints that send device-specific | ||
* port-write messages. End-point messages expected to be handled | ||
* completely by EP specific device driver. | ||
* For switches rc==0 signals that no standard processing required. | ||
*/ | ||
if (rdev->pwcback != NULL) { | ||
if (rdev && rdev->pwcback) { | ||
rc = rdev->pwcback(rdev, pw_msg, 0); | ||
if (rc == 0) | ||
return 0; | ||
} | ||
|
||
mutex_lock(&mport->lock); | ||
list_for_each_entry(pwrite, &mport->pwrites, node) | ||
pwrite->pwcback(mport, pwrite->context, pw_msg, 0); | ||
mutex_unlock(&mport->lock); | ||
|
||
if (!rdev) | ||
return 0; | ||
|
||
/* | ||
* FIXME: The code below stays as it was before for now until we decide | ||
* how to do default PW handling in combination with per-mport callbacks | ||
*/ | ||
|
||
portnum = pw_msg->em.is_port & 0xFF; | ||
|
||
/* Check if device and route to it are functional: | ||
|
@@ -2060,6 +2153,7 @@ int rio_mport_initialize(struct rio_mport *mport) | |
mport->nscan = NULL; | ||
mutex_init(&mport->lock); | ||
mport->pwe_refcnt = 0; | ||
INIT_LIST_HEAD(&mport->pwrites); | ||
|
||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters