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