Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *   This file is provided under a dual BSD/GPLv2 license.  When using or
0003  *   redistributing this file, you may do so under either license.
0004  *
0005  *   GPL LICENSE SUMMARY
0006  *
0007  *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
0008  *   Copyright (C) 2017 T-Platforms. All Rights Reserved.
0009  *
0010  *   This program is free software; you can redistribute it and/or modify
0011  *   it under the terms of version 2 of the GNU General Public License as
0012  *   published by the Free Software Foundation.
0013  *
0014  *   This program is distributed in the hope that it will be useful, but
0015  *   WITHOUT ANY WARRANTY; without even the implied warranty of
0016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017  *   General Public License for more details.
0018  *
0019  *   BSD LICENSE
0020  *
0021  *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
0022  *   Copyright (C) 2017 T-Platforms. All Rights Reserved.
0023  *
0024  *   Redistribution and use in source and binary forms, with or without
0025  *   modification, are permitted provided that the following conditions
0026  *   are met:
0027  *
0028  *     * Redistributions of source code must retain the above copyright
0029  *       notice, this list of conditions and the following disclaimer.
0030  *     * Redistributions in binary form must reproduce the above copy
0031  *       notice, this list of conditions and the following disclaimer in
0032  *       the documentation and/or other materials provided with the
0033  *       distribution.
0034  *     * Neither the name of Intel Corporation nor the names of its
0035  *       contributors may be used to endorse or promote products derived
0036  *       from this software without specific prior written permission.
0037  *
0038  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0039  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0040  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0041  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0042  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0043  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0044  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0045  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0046  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0047  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0048  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0049  *
0050  * PCIe NTB Pingpong Linux driver
0051  */
0052 
0053 /*
0054  * How to use this tool, by example.
0055  *
0056  * Assuming $DBG_DIR is something like:
0057  * '/sys/kernel/debug/ntb_perf/0000:00:03.0'
0058  * Suppose aside from local device there is at least one remote device
0059  * connected to NTB with index 0.
0060  *-----------------------------------------------------------------------------
0061  * Eg: install driver with specified delay between doorbell event and response
0062  *
0063  * root@self# insmod ntb_pingpong.ko delay_ms=1000
0064  *-----------------------------------------------------------------------------
0065  * Eg: get number of ping-pong cycles performed
0066  *
0067  * root@self# cat $DBG_DIR/count
0068  */
0069 
0070 #include <linux/init.h>
0071 #include <linux/kernel.h>
0072 #include <linux/module.h>
0073 #include <linux/device.h>
0074 #include <linux/bitops.h>
0075 
0076 #include <linux/pci.h>
0077 #include <linux/slab.h>
0078 #include <linux/hrtimer.h>
0079 #include <linux/debugfs.h>
0080 
0081 #include <linux/ntb.h>
0082 
0083 #define DRIVER_NAME     "ntb_pingpong"
0084 #define DRIVER_VERSION      "2.0"
0085 
0086 MODULE_LICENSE("Dual BSD/GPL");
0087 MODULE_VERSION(DRIVER_VERSION);
0088 MODULE_AUTHOR("Allen Hubbe <Allen.Hubbe@emc.com>");
0089 MODULE_DESCRIPTION("PCIe NTB Simple Pingpong Client");
0090 
0091 static unsigned int unsafe;
0092 module_param(unsafe, uint, 0644);
0093 MODULE_PARM_DESC(unsafe, "Run even though ntb operations may be unsafe");
0094 
0095 static unsigned int delay_ms = 1000;
0096 module_param(delay_ms, uint, 0644);
0097 MODULE_PARM_DESC(delay_ms, "Milliseconds to delay the response to peer");
0098 
0099 struct pp_ctx {
0100     struct ntb_dev *ntb;
0101     struct hrtimer timer;
0102     u64 in_db;
0103     u64 out_db;
0104     int out_pidx;
0105     u64 nmask;
0106     u64 pmask;
0107     atomic_t count;
0108     spinlock_t lock;
0109     struct dentry *dbgfs_dir;
0110 };
0111 #define to_pp_timer(__timer) \
0112     container_of(__timer, struct pp_ctx, timer)
0113 
0114 static struct dentry *pp_dbgfs_topdir;
0115 
0116 static int pp_find_next_peer(struct pp_ctx *pp)
0117 {
0118     u64 link, out_db;
0119     int pidx;
0120 
0121     link = ntb_link_is_up(pp->ntb, NULL, NULL);
0122 
0123     /* Find next available peer */
0124     if (link & pp->nmask)
0125         pidx = __ffs64(link & pp->nmask);
0126     else if (link & pp->pmask)
0127         pidx = __ffs64(link & pp->pmask);
0128     else
0129         return -ENODEV;
0130 
0131     out_db = BIT_ULL(ntb_peer_port_number(pp->ntb, pidx));
0132 
0133     spin_lock(&pp->lock);
0134     pp->out_pidx = pidx;
0135     pp->out_db = out_db;
0136     spin_unlock(&pp->lock);
0137 
0138     return 0;
0139 }
0140 
0141 static void pp_setup(struct pp_ctx *pp)
0142 {
0143     int ret;
0144 
0145     ntb_db_set_mask(pp->ntb, pp->in_db);
0146 
0147     hrtimer_cancel(&pp->timer);
0148 
0149     ret = pp_find_next_peer(pp);
0150     if (ret == -ENODEV) {
0151         dev_dbg(&pp->ntb->dev, "Got no peers, so cancel\n");
0152         return;
0153     }
0154 
0155     dev_dbg(&pp->ntb->dev, "Ping-pong started with port %d, db %#llx\n",
0156         ntb_peer_port_number(pp->ntb, pp->out_pidx), pp->out_db);
0157 
0158     hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL);
0159 }
0160 
0161 static void pp_clear(struct pp_ctx *pp)
0162 {
0163     hrtimer_cancel(&pp->timer);
0164 
0165     ntb_db_set_mask(pp->ntb, pp->in_db);
0166 
0167     dev_dbg(&pp->ntb->dev, "Ping-pong cancelled\n");
0168 }
0169 
0170 static void pp_ping(struct pp_ctx *pp)
0171 {
0172     u32 count;
0173 
0174     count = atomic_read(&pp->count);
0175 
0176     spin_lock(&pp->lock);
0177     ntb_peer_spad_write(pp->ntb, pp->out_pidx, 0, count);
0178     ntb_peer_msg_write(pp->ntb, pp->out_pidx, 0, count);
0179 
0180     dev_dbg(&pp->ntb->dev, "Ping port %d spad %#x, msg %#x\n",
0181         ntb_peer_port_number(pp->ntb, pp->out_pidx), count, count);
0182 
0183     ntb_peer_db_set(pp->ntb, pp->out_db);
0184     ntb_db_clear_mask(pp->ntb, pp->in_db);
0185     spin_unlock(&pp->lock);
0186 }
0187 
0188 static void pp_pong(struct pp_ctx *pp)
0189 {
0190     u32 msg_data, spad_data;
0191     int pidx = 0;
0192 
0193     /* Read pong data */
0194     spad_data = ntb_spad_read(pp->ntb, 0);
0195     msg_data = ntb_msg_read(pp->ntb, &pidx, 0);
0196     ntb_msg_clear_sts(pp->ntb, -1);
0197 
0198     /*
0199      * Scratchpad and message data may differ, since message register can't
0200      * be rewritten unless status is cleared. Additionally either of them
0201      * might be unsupported
0202      */
0203     dev_dbg(&pp->ntb->dev, "Pong spad %#x, msg %#x (port %d)\n",
0204         spad_data, msg_data, ntb_peer_port_number(pp->ntb, pidx));
0205 
0206     atomic_inc(&pp->count);
0207 
0208     ntb_db_set_mask(pp->ntb, pp->in_db);
0209     ntb_db_clear(pp->ntb, pp->in_db);
0210 
0211     hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL);
0212 }
0213 
0214 static enum hrtimer_restart pp_timer_func(struct hrtimer *t)
0215 {
0216     struct pp_ctx *pp = to_pp_timer(t);
0217 
0218     pp_ping(pp);
0219 
0220     return HRTIMER_NORESTART;
0221 }
0222 
0223 static void pp_link_event(void *ctx)
0224 {
0225     struct pp_ctx *pp = ctx;
0226 
0227     pp_setup(pp);
0228 }
0229 
0230 static void pp_db_event(void *ctx, int vec)
0231 {
0232     struct pp_ctx *pp = ctx;
0233 
0234     pp_pong(pp);
0235 }
0236 
0237 static const struct ntb_ctx_ops pp_ops = {
0238     .link_event = pp_link_event,
0239     .db_event = pp_db_event
0240 };
0241 
0242 static int pp_check_ntb(struct ntb_dev *ntb)
0243 {
0244     u64 pmask;
0245 
0246     if (ntb_db_is_unsafe(ntb)) {
0247         dev_dbg(&ntb->dev, "Doorbell is unsafe\n");
0248         if (!unsafe)
0249             return -EINVAL;
0250     }
0251 
0252     if (ntb_spad_is_unsafe(ntb)) {
0253         dev_dbg(&ntb->dev, "Scratchpad is unsafe\n");
0254         if (!unsafe)
0255             return -EINVAL;
0256     }
0257 
0258     pmask = GENMASK_ULL(ntb_peer_port_count(ntb), 0);
0259     if ((ntb_db_valid_mask(ntb) & pmask) != pmask) {
0260         dev_err(&ntb->dev, "Unsupported DB configuration\n");
0261         return -EINVAL;
0262     }
0263 
0264     if (ntb_spad_count(ntb) < 1 && ntb_msg_count(ntb) < 1) {
0265         dev_err(&ntb->dev, "Scratchpads and messages unsupported\n");
0266         return -EINVAL;
0267     } else if (ntb_spad_count(ntb) < 1) {
0268         dev_dbg(&ntb->dev, "Scratchpads unsupported\n");
0269     } else if (ntb_msg_count(ntb) < 1) {
0270         dev_dbg(&ntb->dev, "Messages unsupported\n");
0271     }
0272 
0273     return 0;
0274 }
0275 
0276 static struct pp_ctx *pp_create_data(struct ntb_dev *ntb)
0277 {
0278     struct pp_ctx *pp;
0279 
0280     pp = devm_kzalloc(&ntb->dev, sizeof(*pp), GFP_KERNEL);
0281     if (!pp)
0282         return ERR_PTR(-ENOMEM);
0283 
0284     pp->ntb = ntb;
0285     atomic_set(&pp->count, 0);
0286     spin_lock_init(&pp->lock);
0287     hrtimer_init(&pp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0288     pp->timer.function = pp_timer_func;
0289 
0290     return pp;
0291 }
0292 
0293 static void pp_init_flds(struct pp_ctx *pp)
0294 {
0295     int pidx, lport, pcnt;
0296 
0297     /* Find global port index */
0298     lport = ntb_port_number(pp->ntb);
0299     pcnt = ntb_peer_port_count(pp->ntb);
0300     for (pidx = 0; pidx < pcnt; pidx++) {
0301         if (lport < ntb_peer_port_number(pp->ntb, pidx))
0302             break;
0303     }
0304 
0305     pp->in_db = BIT_ULL(lport);
0306     pp->pmask = GENMASK_ULL(pidx, 0) >> 1;
0307     pp->nmask = GENMASK_ULL(pcnt - 1, pidx);
0308 
0309     dev_dbg(&pp->ntb->dev, "Inbound db %#llx, prev %#llx, next %#llx\n",
0310         pp->in_db, pp->pmask, pp->nmask);
0311 }
0312 
0313 static int pp_mask_events(struct pp_ctx *pp)
0314 {
0315     u64 db_mask, msg_mask;
0316     int ret;
0317 
0318     db_mask = ntb_db_valid_mask(pp->ntb);
0319     ret = ntb_db_set_mask(pp->ntb, db_mask);
0320     if (ret)
0321         return ret;
0322 
0323     /* Skip message events masking if unsupported */
0324     if (ntb_msg_count(pp->ntb) < 1)
0325         return 0;
0326 
0327     msg_mask = ntb_msg_outbits(pp->ntb) | ntb_msg_inbits(pp->ntb);
0328     return ntb_msg_set_mask(pp->ntb, msg_mask);
0329 }
0330 
0331 static int pp_setup_ctx(struct pp_ctx *pp)
0332 {
0333     int ret;
0334 
0335     ret = ntb_set_ctx(pp->ntb, pp, &pp_ops);
0336     if (ret)
0337         return ret;
0338 
0339     ntb_link_enable(pp->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
0340     /* Might be not necessary */
0341     ntb_link_event(pp->ntb);
0342 
0343     return 0;
0344 }
0345 
0346 static void pp_clear_ctx(struct pp_ctx *pp)
0347 {
0348     ntb_link_disable(pp->ntb);
0349 
0350     ntb_clear_ctx(pp->ntb);
0351 }
0352 
0353 static void pp_setup_dbgfs(struct pp_ctx *pp)
0354 {
0355     struct pci_dev *pdev = pp->ntb->pdev;
0356 
0357     pp->dbgfs_dir = debugfs_create_dir(pci_name(pdev), pp_dbgfs_topdir);
0358 
0359     debugfs_create_atomic_t("count", 0600, pp->dbgfs_dir, &pp->count);
0360 }
0361 
0362 static void pp_clear_dbgfs(struct pp_ctx *pp)
0363 {
0364     debugfs_remove_recursive(pp->dbgfs_dir);
0365 }
0366 
0367 static int pp_probe(struct ntb_client *client, struct ntb_dev *ntb)
0368 {
0369     struct pp_ctx *pp;
0370     int ret;
0371 
0372     ret = pp_check_ntb(ntb);
0373     if (ret)
0374         return ret;
0375 
0376     pp = pp_create_data(ntb);
0377     if (IS_ERR(pp))
0378         return PTR_ERR(pp);
0379 
0380     pp_init_flds(pp);
0381 
0382     ret = pp_mask_events(pp);
0383     if (ret)
0384         return ret;
0385 
0386     ret = pp_setup_ctx(pp);
0387     if (ret)
0388         return ret;
0389 
0390     pp_setup_dbgfs(pp);
0391 
0392     return 0;
0393 }
0394 
0395 static void pp_remove(struct ntb_client *client, struct ntb_dev *ntb)
0396 {
0397     struct pp_ctx *pp = ntb->ctx;
0398 
0399     pp_clear_dbgfs(pp);
0400 
0401     pp_clear_ctx(pp);
0402 
0403     pp_clear(pp);
0404 }
0405 
0406 static struct ntb_client pp_client = {
0407     .ops = {
0408         .probe = pp_probe,
0409         .remove = pp_remove
0410     }
0411 };
0412 
0413 static int __init pp_init(void)
0414 {
0415     int ret;
0416 
0417     if (debugfs_initialized())
0418         pp_dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
0419 
0420     ret = ntb_register_client(&pp_client);
0421     if (ret)
0422         debugfs_remove_recursive(pp_dbgfs_topdir);
0423 
0424     return ret;
0425 }
0426 module_init(pp_init);
0427 
0428 static void __exit pp_exit(void)
0429 {
0430     ntb_unregister_client(&pp_client);
0431     debugfs_remove_recursive(pp_dbgfs_topdir);
0432 }
0433 module_exit(pp_exit);