diff options
author | Logan Gunthorpe <logang@deltatee.com> | 2016-06-20 15:15:10 -0400 |
---|---|---|
committer | Jon Mason <jdmason@kudzu.us> | 2016-08-05 10:21:07 -0400 |
commit | bfcaa39652bf64294261415e5fa18ef0445a4d74 (patch) | |
tree | 7bfc6fd71823bdf697dc64d3ed51e76c3eae7fea | |
parent | 717146a2a8cbf6dbcb8fdf4ae7cddd2d6074161c (diff) |
ntb_tool: Add link status and files to debugfs
In order to more successfully script with ntb_tool it's useful to
have a link file to check the link status so that the script
doesn't use the other files until the link is up.
This commit adds a 'link' file to the debugfs directory which reads
boolean (Y or N) depending on the link status. Writing to the file
change the link state using ntb_link_enable or ntb_link_disable.
A 'link_event' file is also provided so an application can block until
the link changes to the desired state. If the user writes a 1, it will
block until the link is up. If the user writes a 0, it will block until
the link is down.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Allen Hubbe <Allen.Hubbe@emc.com>
Signed-off-by: Jon Mason <jdmason@kudzu.us>
-rw-r--r-- | drivers/ntb/test/ntb_tool.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c index 1509b4c1f204..61bf2ef87e0e 100644 --- a/drivers/ntb/test/ntb_tool.c +++ b/drivers/ntb/test/ntb_tool.c | |||
@@ -59,6 +59,12 @@ | |||
59 | * | 59 | * |
60 | * Eg: check if clearing the doorbell mask generates an interrupt. | 60 | * Eg: check if clearing the doorbell mask generates an interrupt. |
61 | * | 61 | * |
62 | * # Check the link status | ||
63 | * root@self# cat $DBG_DIR/link | ||
64 | * | ||
65 | * # Block until the link is up | ||
66 | * root@self# echo Y > $DBG_DIR/link_event | ||
67 | * | ||
62 | * # Set the doorbell mask | 68 | * # Set the doorbell mask |
63 | * root@self# echo 's 1' > $DBG_DIR/mask | 69 | * root@self# echo 's 1' > $DBG_DIR/mask |
64 | * | 70 | * |
@@ -131,6 +137,7 @@ struct tool_mw { | |||
131 | struct tool_ctx { | 137 | struct tool_ctx { |
132 | struct ntb_dev *ntb; | 138 | struct ntb_dev *ntb; |
133 | struct dentry *dbgfs; | 139 | struct dentry *dbgfs; |
140 | wait_queue_head_t link_wq; | ||
134 | int mw_count; | 141 | int mw_count; |
135 | struct tool_mw mws[MAX_MWS]; | 142 | struct tool_mw mws[MAX_MWS]; |
136 | }; | 143 | }; |
@@ -159,6 +166,7 @@ static void tool_link_event(void *ctx) | |||
159 | dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n", | 166 | dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n", |
160 | up ? "up" : "down", speed, width); | 167 | up ? "up" : "down", speed, width); |
161 | 168 | ||
169 | wake_up(&tc->link_wq); | ||
162 | } | 170 | } |
163 | 171 | ||
164 | static void tool_db_event(void *ctx, int vec) | 172 | static void tool_db_event(void *ctx, int vec) |
@@ -473,6 +481,83 @@ static TOOL_FOPS_RDWR(tool_peer_spad_fops, | |||
473 | tool_peer_spad_read, | 481 | tool_peer_spad_read, |
474 | tool_peer_spad_write); | 482 | tool_peer_spad_write); |
475 | 483 | ||
484 | static ssize_t tool_link_read(struct file *filep, char __user *ubuf, | ||
485 | size_t size, loff_t *offp) | ||
486 | { | ||
487 | struct tool_ctx *tc = filep->private_data; | ||
488 | char buf[3]; | ||
489 | |||
490 | buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N'; | ||
491 | buf[1] = '\n'; | ||
492 | buf[2] = '\0'; | ||
493 | |||
494 | return simple_read_from_buffer(ubuf, size, offp, buf, 2); | ||
495 | } | ||
496 | |||
497 | static ssize_t tool_link_write(struct file *filep, const char __user *ubuf, | ||
498 | size_t size, loff_t *offp) | ||
499 | { | ||
500 | struct tool_ctx *tc = filep->private_data; | ||
501 | char buf[32]; | ||
502 | size_t buf_size; | ||
503 | bool val; | ||
504 | int rc; | ||
505 | |||
506 | buf_size = min(size, (sizeof(buf) - 1)); | ||
507 | if (copy_from_user(buf, ubuf, buf_size)) | ||
508 | return -EFAULT; | ||
509 | |||
510 | buf[buf_size] = '\0'; | ||
511 | |||
512 | rc = strtobool(buf, &val); | ||
513 | if (rc) | ||
514 | return rc; | ||
515 | |||
516 | if (val) | ||
517 | rc = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO); | ||
518 | else | ||
519 | rc = ntb_link_disable(tc->ntb); | ||
520 | |||
521 | if (rc) | ||
522 | return rc; | ||
523 | |||
524 | return size; | ||
525 | } | ||
526 | |||
527 | static TOOL_FOPS_RDWR(tool_link_fops, | ||
528 | tool_link_read, | ||
529 | tool_link_write); | ||
530 | |||
531 | static ssize_t tool_link_event_write(struct file *filep, | ||
532 | const char __user *ubuf, | ||
533 | size_t size, loff_t *offp) | ||
534 | { | ||
535 | struct tool_ctx *tc = filep->private_data; | ||
536 | char buf[32]; | ||
537 | size_t buf_size; | ||
538 | bool val; | ||
539 | int rc; | ||
540 | |||
541 | buf_size = min(size, (sizeof(buf) - 1)); | ||
542 | if (copy_from_user(buf, ubuf, buf_size)) | ||
543 | return -EFAULT; | ||
544 | |||
545 | buf[buf_size] = '\0'; | ||
546 | |||
547 | rc = strtobool(buf, &val); | ||
548 | if (rc) | ||
549 | return rc; | ||
550 | |||
551 | if (wait_event_interruptible(tc->link_wq, | ||
552 | ntb_link_is_up(tc->ntb, NULL, NULL) == val)) | ||
553 | return -ERESTART; | ||
554 | |||
555 | return size; | ||
556 | } | ||
557 | |||
558 | static TOOL_FOPS_RDWR(tool_link_event_fops, | ||
559 | NULL, | ||
560 | tool_link_event_write); | ||
476 | 561 | ||
477 | static ssize_t tool_mw_read(struct file *filep, char __user *ubuf, | 562 | static ssize_t tool_mw_read(struct file *filep, char __user *ubuf, |
478 | size_t size, loff_t *offp) | 563 | size_t size, loff_t *offp) |
@@ -803,6 +888,12 @@ static void tool_setup_dbgfs(struct tool_ctx *tc) | |||
803 | debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs, | 888 | debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs, |
804 | tc, &tool_peer_spad_fops); | 889 | tc, &tool_peer_spad_fops); |
805 | 890 | ||
891 | debugfs_create_file("link", S_IRUSR | S_IWUSR, tc->dbgfs, | ||
892 | tc, &tool_link_fops); | ||
893 | |||
894 | debugfs_create_file("link_event", S_IWUSR, tc->dbgfs, | ||
895 | tc, &tool_link_event_fops); | ||
896 | |||
806 | for (i = 0; i < tc->mw_count; i++) { | 897 | for (i = 0; i < tc->mw_count; i++) { |
807 | char buf[30]; | 898 | char buf[30]; |
808 | 899 | ||
@@ -835,6 +926,7 @@ static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb) | |||
835 | } | 926 | } |
836 | 927 | ||
837 | tc->ntb = ntb; | 928 | tc->ntb = ntb; |
929 | init_waitqueue_head(&tc->link_wq); | ||
838 | 930 | ||
839 | tc->mw_count = min(ntb_mw_count(tc->ntb), MAX_MWS); | 931 | tc->mw_count = min(ntb_mw_count(tc->ntb), MAX_MWS); |
840 | for (i = 0; i < tc->mw_count; i++) { | 932 | for (i = 0; i < tc->mw_count; i++) { |