core.c (7836B)
1/* 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright (C) 2015 EMC Corporation. All Rights Reserved. 8 * Copyright (C) 2016 T-Platforms. All Rights Reserved. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of version 2 of the GNU General Public License as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * BSD LICENSE 20 * 21 * Copyright (C) 2015 EMC Corporation. All Rights Reserved. 22 * Copyright (C) 2016 T-Platforms. All Rights Reserved. 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 28 * * Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * * Redistributions in binary form must reproduce the above copy 31 * notice, this list of conditions and the following disclaimer in 32 * the documentation and/or other materials provided with the 33 * distribution. 34 * * Neither the name of Intel Corporation nor the names of its 35 * contributors may be used to endorse or promote products derived 36 * from this software without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 39 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 40 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 41 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 42 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 44 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 48 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 49 * 50 * PCIe NTB Linux driver 51 * 52 * Contact Information: 53 * Allen Hubbe <Allen.Hubbe@emc.com> 54 */ 55 56#include <linux/device.h> 57#include <linux/kernel.h> 58#include <linux/module.h> 59 60#include <linux/ntb.h> 61#include <linux/pci.h> 62 63#define DRIVER_NAME "ntb" 64#define DRIVER_DESCRIPTION "PCIe NTB Driver Framework" 65 66#define DRIVER_VERSION "1.0" 67#define DRIVER_RELDATE "24 March 2015" 68#define DRIVER_AUTHOR "Allen Hubbe <Allen.Hubbe@emc.com>" 69 70MODULE_LICENSE("Dual BSD/GPL"); 71MODULE_VERSION(DRIVER_VERSION); 72MODULE_AUTHOR(DRIVER_AUTHOR); 73MODULE_DESCRIPTION(DRIVER_DESCRIPTION); 74 75static struct bus_type ntb_bus; 76static void ntb_dev_release(struct device *dev); 77 78int __ntb_register_client(struct ntb_client *client, struct module *mod, 79 const char *mod_name) 80{ 81 if (!client) 82 return -EINVAL; 83 if (!ntb_client_ops_is_valid(&client->ops)) 84 return -EINVAL; 85 86 memset(&client->drv, 0, sizeof(client->drv)); 87 client->drv.bus = &ntb_bus; 88 client->drv.name = mod_name; 89 client->drv.owner = mod; 90 91 return driver_register(&client->drv); 92} 93EXPORT_SYMBOL(__ntb_register_client); 94 95void ntb_unregister_client(struct ntb_client *client) 96{ 97 driver_unregister(&client->drv); 98} 99EXPORT_SYMBOL(ntb_unregister_client); 100 101int ntb_register_device(struct ntb_dev *ntb) 102{ 103 if (!ntb) 104 return -EINVAL; 105 if (!ntb->pdev) 106 return -EINVAL; 107 if (!ntb->ops) 108 return -EINVAL; 109 if (!ntb_dev_ops_is_valid(ntb->ops)) 110 return -EINVAL; 111 112 init_completion(&ntb->released); 113 114 ntb->dev.bus = &ntb_bus; 115 ntb->dev.parent = &ntb->pdev->dev; 116 ntb->dev.release = ntb_dev_release; 117 dev_set_name(&ntb->dev, "%s", pci_name(ntb->pdev)); 118 119 ntb->ctx = NULL; 120 ntb->ctx_ops = NULL; 121 spin_lock_init(&ntb->ctx_lock); 122 123 return device_register(&ntb->dev); 124} 125EXPORT_SYMBOL(ntb_register_device); 126 127void ntb_unregister_device(struct ntb_dev *ntb) 128{ 129 device_unregister(&ntb->dev); 130 wait_for_completion(&ntb->released); 131} 132EXPORT_SYMBOL(ntb_unregister_device); 133 134int ntb_set_ctx(struct ntb_dev *ntb, void *ctx, 135 const struct ntb_ctx_ops *ctx_ops) 136{ 137 unsigned long irqflags; 138 139 if (!ntb_ctx_ops_is_valid(ctx_ops)) 140 return -EINVAL; 141 if (ntb->ctx_ops) 142 return -EINVAL; 143 144 spin_lock_irqsave(&ntb->ctx_lock, irqflags); 145 { 146 ntb->ctx = ctx; 147 ntb->ctx_ops = ctx_ops; 148 } 149 spin_unlock_irqrestore(&ntb->ctx_lock, irqflags); 150 151 return 0; 152} 153EXPORT_SYMBOL(ntb_set_ctx); 154 155void ntb_clear_ctx(struct ntb_dev *ntb) 156{ 157 unsigned long irqflags; 158 159 spin_lock_irqsave(&ntb->ctx_lock, irqflags); 160 { 161 ntb->ctx_ops = NULL; 162 ntb->ctx = NULL; 163 } 164 spin_unlock_irqrestore(&ntb->ctx_lock, irqflags); 165} 166EXPORT_SYMBOL(ntb_clear_ctx); 167 168void ntb_link_event(struct ntb_dev *ntb) 169{ 170 unsigned long irqflags; 171 172 spin_lock_irqsave(&ntb->ctx_lock, irqflags); 173 { 174 if (ntb->ctx_ops && ntb->ctx_ops->link_event) 175 ntb->ctx_ops->link_event(ntb->ctx); 176 } 177 spin_unlock_irqrestore(&ntb->ctx_lock, irqflags); 178} 179EXPORT_SYMBOL(ntb_link_event); 180 181void ntb_db_event(struct ntb_dev *ntb, int vector) 182{ 183 unsigned long irqflags; 184 185 spin_lock_irqsave(&ntb->ctx_lock, irqflags); 186 { 187 if (ntb->ctx_ops && ntb->ctx_ops->db_event) 188 ntb->ctx_ops->db_event(ntb->ctx, vector); 189 } 190 spin_unlock_irqrestore(&ntb->ctx_lock, irqflags); 191} 192EXPORT_SYMBOL(ntb_db_event); 193 194void ntb_msg_event(struct ntb_dev *ntb) 195{ 196 unsigned long irqflags; 197 198 spin_lock_irqsave(&ntb->ctx_lock, irqflags); 199 { 200 if (ntb->ctx_ops && ntb->ctx_ops->msg_event) 201 ntb->ctx_ops->msg_event(ntb->ctx); 202 } 203 spin_unlock_irqrestore(&ntb->ctx_lock, irqflags); 204} 205EXPORT_SYMBOL(ntb_msg_event); 206 207int ntb_default_port_number(struct ntb_dev *ntb) 208{ 209 switch (ntb->topo) { 210 case NTB_TOPO_PRI: 211 case NTB_TOPO_B2B_USD: 212 return NTB_PORT_PRI_USD; 213 case NTB_TOPO_SEC: 214 case NTB_TOPO_B2B_DSD: 215 return NTB_PORT_SEC_DSD; 216 default: 217 return 0; 218 } 219} 220EXPORT_SYMBOL(ntb_default_port_number); 221 222int ntb_default_peer_port_count(struct ntb_dev *ntb) 223{ 224 return NTB_DEF_PEER_CNT; 225} 226EXPORT_SYMBOL(ntb_default_peer_port_count); 227 228int ntb_default_peer_port_number(struct ntb_dev *ntb, int pidx) 229{ 230 if (pidx != NTB_DEF_PEER_IDX) 231 return -EINVAL; 232 233 switch (ntb->topo) { 234 case NTB_TOPO_PRI: 235 case NTB_TOPO_B2B_USD: 236 return NTB_PORT_SEC_DSD; 237 case NTB_TOPO_SEC: 238 case NTB_TOPO_B2B_DSD: 239 return NTB_PORT_PRI_USD; 240 default: 241 return 0; 242 } 243} 244EXPORT_SYMBOL(ntb_default_peer_port_number); 245 246int ntb_default_peer_port_idx(struct ntb_dev *ntb, int port) 247{ 248 int peer_port = ntb_default_peer_port_number(ntb, NTB_DEF_PEER_IDX); 249 250 if (peer_port == -EINVAL || port != peer_port) 251 return -EINVAL; 252 253 return 0; 254} 255EXPORT_SYMBOL(ntb_default_peer_port_idx); 256 257static int ntb_probe(struct device *dev) 258{ 259 struct ntb_dev *ntb; 260 struct ntb_client *client; 261 int rc; 262 263 get_device(dev); 264 ntb = dev_ntb(dev); 265 client = drv_ntb_client(dev->driver); 266 267 rc = client->ops.probe(client, ntb); 268 if (rc) 269 put_device(dev); 270 271 return rc; 272} 273 274static void ntb_remove(struct device *dev) 275{ 276 struct ntb_dev *ntb; 277 struct ntb_client *client; 278 279 if (dev->driver) { 280 ntb = dev_ntb(dev); 281 client = drv_ntb_client(dev->driver); 282 283 client->ops.remove(client, ntb); 284 put_device(dev); 285 } 286} 287 288static void ntb_dev_release(struct device *dev) 289{ 290 struct ntb_dev *ntb = dev_ntb(dev); 291 292 complete(&ntb->released); 293} 294 295static struct bus_type ntb_bus = { 296 .name = "ntb", 297 .probe = ntb_probe, 298 .remove = ntb_remove, 299}; 300 301static int __init ntb_driver_init(void) 302{ 303 return bus_register(&ntb_bus); 304} 305module_init(ntb_driver_init); 306 307static void __exit ntb_driver_exit(void) 308{ 309 bus_unregister(&ntb_bus); 310} 311module_exit(ntb_driver_exit);