xref: /linux/drivers/infiniband/hw/usnic/usnic_ib_main.c (revision 459cc69fa4c17caf21de596693d8a07170820a58)
1e3cf00d0SUpinder Malhi /*
2e3cf00d0SUpinder Malhi  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
3e3cf00d0SUpinder Malhi  *
43805eadeSJeff Squyres  * This software is available to you under a choice of one of two
53805eadeSJeff Squyres  * licenses.  You may choose to be licensed under the terms of the GNU
63805eadeSJeff Squyres  * General Public License (GPL) Version 2, available from the file
73805eadeSJeff Squyres  * COPYING in the main directory of this source tree, or the
83805eadeSJeff Squyres  * BSD license below:
93805eadeSJeff Squyres  *
103805eadeSJeff Squyres  *     Redistribution and use in source and binary forms, with or
113805eadeSJeff Squyres  *     without modification, are permitted provided that the following
123805eadeSJeff Squyres  *     conditions are met:
133805eadeSJeff Squyres  *
143805eadeSJeff Squyres  *      - Redistributions of source code must retain the above
153805eadeSJeff Squyres  *        copyright notice, this list of conditions and the following
163805eadeSJeff Squyres  *        disclaimer.
173805eadeSJeff Squyres  *
183805eadeSJeff Squyres  *      - Redistributions in binary form must reproduce the above
193805eadeSJeff Squyres  *        copyright notice, this list of conditions and the following
203805eadeSJeff Squyres  *        disclaimer in the documentation and/or other materials
213805eadeSJeff Squyres  *        provided with the distribution.
22e3cf00d0SUpinder Malhi  *
23e3cf00d0SUpinder Malhi  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e3cf00d0SUpinder Malhi  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e3cf00d0SUpinder Malhi  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e3cf00d0SUpinder Malhi  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e3cf00d0SUpinder Malhi  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e3cf00d0SUpinder Malhi  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e3cf00d0SUpinder Malhi  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e3cf00d0SUpinder Malhi  * SOFTWARE.
31e3cf00d0SUpinder Malhi  *
32e3cf00d0SUpinder Malhi  * Author: Upinder Malhi <umalhi@cisco.com>
33e3cf00d0SUpinder Malhi  * Author: Anant Deepak <anadeepa@cisco.com>
34e3cf00d0SUpinder Malhi  * Author: Cesare Cantu' <cantuc@cisco.com>
35e3cf00d0SUpinder Malhi  * Author: Jeff Squyres <jsquyres@cisco.com>
36e3cf00d0SUpinder Malhi  * Author: Kiran Thirumalai <kithirum@cisco.com>
37e3cf00d0SUpinder Malhi  * Author: Xuyang Wang <xuywang@cisco.com>
38e3cf00d0SUpinder Malhi  * Author: Reese Faucette <rfaucett@cisco.com>
39e3cf00d0SUpinder Malhi  *
40e3cf00d0SUpinder Malhi  */
41e3cf00d0SUpinder Malhi 
42e3cf00d0SUpinder Malhi #include <linux/module.h>
43c7845bcaSUpinder Malhi #include <linux/inetdevice.h>
44e3cf00d0SUpinder Malhi #include <linux/init.h>
45e3cf00d0SUpinder Malhi #include <linux/slab.h>
46e3cf00d0SUpinder Malhi #include <linux/errno.h>
47e3cf00d0SUpinder Malhi #include <linux/pci.h>
48e3cf00d0SUpinder Malhi #include <linux/netdevice.h>
49e3cf00d0SUpinder Malhi 
50e3cf00d0SUpinder Malhi #include <rdma/ib_user_verbs.h>
51e3cf00d0SUpinder Malhi #include <rdma/ib_addr.h>
52e3cf00d0SUpinder Malhi 
53e3cf00d0SUpinder Malhi #include "usnic_abi.h"
54e3cf00d0SUpinder Malhi #include "usnic_common_util.h"
55e3cf00d0SUpinder Malhi #include "usnic_ib.h"
56e3cf00d0SUpinder Malhi #include "usnic_ib_qp_grp.h"
57e3cf00d0SUpinder Malhi #include "usnic_log.h"
58e3cf00d0SUpinder Malhi #include "usnic_fwd.h"
59e3cf00d0SUpinder Malhi #include "usnic_debugfs.h"
60e3cf00d0SUpinder Malhi #include "usnic_ib_verbs.h"
61e3cf00d0SUpinder Malhi #include "usnic_transport.h"
62e3cf00d0SUpinder Malhi #include "usnic_uiom.h"
63e3cf00d0SUpinder Malhi #include "usnic_ib_sysfs.h"
64e3cf00d0SUpinder Malhi 
65e3cf00d0SUpinder Malhi unsigned int usnic_log_lvl = USNIC_LOG_LVL_ERR;
66e3cf00d0SUpinder Malhi unsigned int usnic_ib_share_vf = 1;
67e3cf00d0SUpinder Malhi 
68e3cf00d0SUpinder Malhi static const char usnic_version[] =
69e3cf00d0SUpinder Malhi 	DRV_NAME ": Cisco VIC (USNIC) Verbs Driver v"
70e3cf00d0SUpinder Malhi 	DRV_VERSION " (" DRV_RELDATE ")\n";
71e3cf00d0SUpinder Malhi 
72e3cf00d0SUpinder Malhi static DEFINE_MUTEX(usnic_ib_ibdev_list_lock);
73e3cf00d0SUpinder Malhi static LIST_HEAD(usnic_ib_ibdev_list);
74e3cf00d0SUpinder Malhi 
75e3cf00d0SUpinder Malhi /* Callback dump funcs */
76e3cf00d0SUpinder Malhi static int usnic_ib_dump_vf_hdr(void *obj, char *buf, int buf_sz)
77e3cf00d0SUpinder Malhi {
78e3cf00d0SUpinder Malhi 	struct usnic_ib_vf *vf = obj;
799de69861SJason Gunthorpe 	return scnprintf(buf, buf_sz, "PF: %s ", dev_name(&vf->pf->ib_dev.dev));
80e3cf00d0SUpinder Malhi }
81e3cf00d0SUpinder Malhi /* End callback dump funcs */
82e3cf00d0SUpinder Malhi 
83e3cf00d0SUpinder Malhi static void usnic_ib_dump_vf(struct usnic_ib_vf *vf, char *buf, int buf_sz)
84e3cf00d0SUpinder Malhi {
85e3cf00d0SUpinder Malhi 	usnic_vnic_dump(vf->vnic, buf, buf_sz, vf,
86e3cf00d0SUpinder Malhi 			usnic_ib_dump_vf_hdr,
87e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_dump_hdr, usnic_ib_qp_grp_dump_rows);
88e3cf00d0SUpinder Malhi }
89e3cf00d0SUpinder Malhi 
90e3cf00d0SUpinder Malhi void usnic_ib_log_vf(struct usnic_ib_vf *vf)
91e3cf00d0SUpinder Malhi {
92e3cf00d0SUpinder Malhi 	char buf[1000];
93e3cf00d0SUpinder Malhi 	usnic_ib_dump_vf(vf, buf, sizeof(buf));
94e3cf00d0SUpinder Malhi 	usnic_dbg("%s\n", buf);
95e3cf00d0SUpinder Malhi }
96e3cf00d0SUpinder Malhi 
97e3cf00d0SUpinder Malhi /* Start of netdev section */
98e3cf00d0SUpinder Malhi static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev)
99e3cf00d0SUpinder Malhi {
100e3cf00d0SUpinder Malhi 	struct usnic_ib_ucontext *ctx;
101e3cf00d0SUpinder Malhi 	struct usnic_ib_qp_grp *qp_grp;
102e3cf00d0SUpinder Malhi 	enum ib_qp_state cur_state;
103e3cf00d0SUpinder Malhi 	int status;
104e3cf00d0SUpinder Malhi 
105e3cf00d0SUpinder Malhi 	BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
106e3cf00d0SUpinder Malhi 
107e3cf00d0SUpinder Malhi 	list_for_each_entry(ctx, &us_ibdev->ctx_list, link) {
108e3cf00d0SUpinder Malhi 		list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) {
109e3cf00d0SUpinder Malhi 			cur_state = qp_grp->state;
110e3cf00d0SUpinder Malhi 			if (cur_state == IB_QPS_INIT ||
111e3cf00d0SUpinder Malhi 				cur_state == IB_QPS_RTR ||
112e3cf00d0SUpinder Malhi 				cur_state == IB_QPS_RTS) {
113e3cf00d0SUpinder Malhi 				status = usnic_ib_qp_grp_modify(qp_grp,
114e3cf00d0SUpinder Malhi 								IB_QPS_ERR,
115e3cf00d0SUpinder Malhi 								NULL);
116e3cf00d0SUpinder Malhi 				if (status) {
117e3cf00d0SUpinder Malhi 					usnic_err("Failed to transistion qp grp %u from %s to %s\n",
118e3cf00d0SUpinder Malhi 						qp_grp->grp_id,
119e3cf00d0SUpinder Malhi 						usnic_ib_qp_grp_state_to_string
120e3cf00d0SUpinder Malhi 						(cur_state),
121e3cf00d0SUpinder Malhi 						usnic_ib_qp_grp_state_to_string
122e3cf00d0SUpinder Malhi 						(IB_QPS_ERR));
123e3cf00d0SUpinder Malhi 				}
124e3cf00d0SUpinder Malhi 			}
125e3cf00d0SUpinder Malhi 		}
126e3cf00d0SUpinder Malhi 	}
127e3cf00d0SUpinder Malhi }
128e3cf00d0SUpinder Malhi 
129e3cf00d0SUpinder Malhi static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev,
130e3cf00d0SUpinder Malhi 					unsigned long event)
131e3cf00d0SUpinder Malhi {
132e3cf00d0SUpinder Malhi 	struct net_device *netdev;
133e3cf00d0SUpinder Malhi 	struct ib_event ib_event;
134e3cf00d0SUpinder Malhi 
135e3cf00d0SUpinder Malhi 	memset(&ib_event, 0, sizeof(ib_event));
136e3cf00d0SUpinder Malhi 
137e3cf00d0SUpinder Malhi 	mutex_lock(&us_ibdev->usdev_lock);
138e3cf00d0SUpinder Malhi 	netdev = us_ibdev->netdev;
139e3cf00d0SUpinder Malhi 	switch (event) {
140e3cf00d0SUpinder Malhi 	case NETDEV_REBOOT:
1419de69861SJason Gunthorpe 		usnic_info("PF Reset on %s\n", dev_name(&us_ibdev->ib_dev.dev));
142e3cf00d0SUpinder Malhi 		usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
143e3cf00d0SUpinder Malhi 		ib_event.event = IB_EVENT_PORT_ERR;
144e3cf00d0SUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
145e3cf00d0SUpinder Malhi 		ib_event.element.port_num = 1;
146e3cf00d0SUpinder Malhi 		ib_dispatch_event(&ib_event);
147e3cf00d0SUpinder Malhi 		break;
148e3cf00d0SUpinder Malhi 	case NETDEV_UP:
149e3cf00d0SUpinder Malhi 	case NETDEV_DOWN:
150e3cf00d0SUpinder Malhi 	case NETDEV_CHANGE:
1518af94ac6SUpinder Malhi 		if (!us_ibdev->ufdev->link_up &&
1528af94ac6SUpinder Malhi 				netif_carrier_ok(netdev)) {
1538af94ac6SUpinder Malhi 			usnic_fwd_carrier_up(us_ibdev->ufdev);
1549de69861SJason Gunthorpe 			usnic_info("Link UP on %s\n",
1559de69861SJason Gunthorpe 				   dev_name(&us_ibdev->ib_dev.dev));
156e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_PORT_ACTIVE;
157e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
158e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
159e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
1608af94ac6SUpinder Malhi 		} else if (us_ibdev->ufdev->link_up &&
1618af94ac6SUpinder Malhi 				!netif_carrier_ok(netdev)) {
1628af94ac6SUpinder Malhi 			usnic_fwd_carrier_down(us_ibdev->ufdev);
1639de69861SJason Gunthorpe 			usnic_info("Link DOWN on %s\n",
1649de69861SJason Gunthorpe 				   dev_name(&us_ibdev->ib_dev.dev));
165e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
166e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_PORT_ERR;
167e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
168e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
169e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
170e3cf00d0SUpinder Malhi 		} else {
171c30392abSRoland Dreier 			usnic_dbg("Ignoring %s on %s\n",
1723e0c2dbfSKirill Tkhai 					netdev_cmd_to_name(event),
1739de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev));
174e3cf00d0SUpinder Malhi 		}
175e3cf00d0SUpinder Malhi 		break;
176e3cf00d0SUpinder Malhi 	case NETDEV_CHANGEADDR:
1778af94ac6SUpinder Malhi 		if (!memcmp(us_ibdev->ufdev->mac, netdev->dev_addr,
1788af94ac6SUpinder Malhi 				sizeof(us_ibdev->ufdev->mac))) {
179c30392abSRoland Dreier 			usnic_dbg("Ignoring addr change on %s\n",
1809de69861SJason Gunthorpe 				  dev_name(&us_ibdev->ib_dev.dev));
181e3cf00d0SUpinder Malhi 		} else {
182e3cf00d0SUpinder Malhi 			usnic_info(" %s old mac: %pM new mac: %pM\n",
1839de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev),
1848af94ac6SUpinder Malhi 					us_ibdev->ufdev->mac,
185e3cf00d0SUpinder Malhi 					netdev->dev_addr);
1868af94ac6SUpinder Malhi 			usnic_fwd_set_mac(us_ibdev->ufdev, netdev->dev_addr);
187e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
188e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_GID_CHANGE;
189e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
190e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
191e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
192e3cf00d0SUpinder Malhi 		}
193e3cf00d0SUpinder Malhi 
194e3cf00d0SUpinder Malhi 		break;
195e3cf00d0SUpinder Malhi 	case NETDEV_CHANGEMTU:
1968af94ac6SUpinder Malhi 		if (us_ibdev->ufdev->mtu != netdev->mtu) {
197e3cf00d0SUpinder Malhi 			usnic_info("MTU Change on %s old: %u new: %u\n",
1989de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev),
1998af94ac6SUpinder Malhi 					us_ibdev->ufdev->mtu, netdev->mtu);
2008af94ac6SUpinder Malhi 			usnic_fwd_set_mtu(us_ibdev->ufdev, netdev->mtu);
201e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
202e3cf00d0SUpinder Malhi 		} else {
203e3cf00d0SUpinder Malhi 			usnic_dbg("Ignoring MTU change on %s\n",
2049de69861SJason Gunthorpe 				  dev_name(&us_ibdev->ib_dev.dev));
205e3cf00d0SUpinder Malhi 		}
206e3cf00d0SUpinder Malhi 		break;
207e3cf00d0SUpinder Malhi 	default:
208c30392abSRoland Dreier 		usnic_dbg("Ignoring event %s on %s",
2093e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
2109de69861SJason Gunthorpe 				dev_name(&us_ibdev->ib_dev.dev));
211e3cf00d0SUpinder Malhi 	}
212e3cf00d0SUpinder Malhi 	mutex_unlock(&us_ibdev->usdev_lock);
213e3cf00d0SUpinder Malhi }
214e3cf00d0SUpinder Malhi 
215e3cf00d0SUpinder Malhi static int usnic_ib_netdevice_event(struct notifier_block *notifier,
216e3cf00d0SUpinder Malhi 					unsigned long event, void *ptr)
217e3cf00d0SUpinder Malhi {
218e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
219e3cf00d0SUpinder Malhi 
220e3cf00d0SUpinder Malhi 	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
221e3cf00d0SUpinder Malhi 
222e3cf00d0SUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
223e3cf00d0SUpinder Malhi 	list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
224e3cf00d0SUpinder Malhi 		if (us_ibdev->netdev == netdev) {
225e3cf00d0SUpinder Malhi 			usnic_ib_handle_usdev_event(us_ibdev, event);
226e3cf00d0SUpinder Malhi 			break;
227e3cf00d0SUpinder Malhi 		}
228e3cf00d0SUpinder Malhi 	}
229e3cf00d0SUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
230e3cf00d0SUpinder Malhi 
231e3cf00d0SUpinder Malhi 	return NOTIFY_DONE;
232e3cf00d0SUpinder Malhi }
233e3cf00d0SUpinder Malhi 
234e3cf00d0SUpinder Malhi static struct notifier_block usnic_ib_netdevice_notifier = {
235e3cf00d0SUpinder Malhi 	.notifier_call = usnic_ib_netdevice_event
236e3cf00d0SUpinder Malhi };
237e3cf00d0SUpinder Malhi /* End of netdev section */
238e3cf00d0SUpinder Malhi 
239c7845bcaSUpinder Malhi /* Start of inet section */
240c7845bcaSUpinder Malhi static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev,
241c7845bcaSUpinder Malhi 					unsigned long event, void *ptr)
242c7845bcaSUpinder Malhi {
243c7845bcaSUpinder Malhi 	struct in_ifaddr *ifa = ptr;
244c7845bcaSUpinder Malhi 	struct ib_event ib_event;
245c7845bcaSUpinder Malhi 
246c7845bcaSUpinder Malhi 	mutex_lock(&us_ibdev->usdev_lock);
247c7845bcaSUpinder Malhi 
248c7845bcaSUpinder Malhi 	switch (event) {
249c7845bcaSUpinder Malhi 	case NETDEV_DOWN:
250c7845bcaSUpinder Malhi 		usnic_info("%s via ip notifiers",
2513e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event));
252c7845bcaSUpinder Malhi 		usnic_fwd_del_ipaddr(us_ibdev->ufdev);
253c7845bcaSUpinder Malhi 		usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
254c7845bcaSUpinder Malhi 		ib_event.event = IB_EVENT_GID_CHANGE;
255c7845bcaSUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
256c7845bcaSUpinder Malhi 		ib_event.element.port_num = 1;
257c7845bcaSUpinder Malhi 		ib_dispatch_event(&ib_event);
258c7845bcaSUpinder Malhi 		break;
259c7845bcaSUpinder Malhi 	case NETDEV_UP:
260c7845bcaSUpinder Malhi 		usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
261c7845bcaSUpinder Malhi 		usnic_info("%s via ip notifiers: ip %pI4",
2623e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
263c7845bcaSUpinder Malhi 				&us_ibdev->ufdev->inaddr);
264c7845bcaSUpinder Malhi 		ib_event.event = IB_EVENT_GID_CHANGE;
265c7845bcaSUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
266c7845bcaSUpinder Malhi 		ib_event.element.port_num = 1;
267c7845bcaSUpinder Malhi 		ib_dispatch_event(&ib_event);
268c7845bcaSUpinder Malhi 		break;
269c7845bcaSUpinder Malhi 	default:
270c30392abSRoland Dreier 		usnic_info("Ignoring event %s on %s",
2713e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
2729de69861SJason Gunthorpe 				dev_name(&us_ibdev->ib_dev.dev));
273c7845bcaSUpinder Malhi 	}
274c7845bcaSUpinder Malhi 	mutex_unlock(&us_ibdev->usdev_lock);
275c7845bcaSUpinder Malhi 
276c7845bcaSUpinder Malhi 	return NOTIFY_DONE;
277c7845bcaSUpinder Malhi }
278c7845bcaSUpinder Malhi 
279c7845bcaSUpinder Malhi static int usnic_ib_inetaddr_event(struct notifier_block *notifier,
280c7845bcaSUpinder Malhi 					unsigned long event, void *ptr)
281c7845bcaSUpinder Malhi {
282c7845bcaSUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
283c7845bcaSUpinder Malhi 	struct in_ifaddr *ifa = ptr;
284c7845bcaSUpinder Malhi 	struct net_device *netdev = ifa->ifa_dev->dev;
285c7845bcaSUpinder Malhi 
286c7845bcaSUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
287c7845bcaSUpinder Malhi 	list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
288c7845bcaSUpinder Malhi 		if (us_ibdev->netdev == netdev) {
289c7845bcaSUpinder Malhi 			usnic_ib_handle_inet_event(us_ibdev, event, ptr);
290c7845bcaSUpinder Malhi 			break;
291c7845bcaSUpinder Malhi 		}
292c7845bcaSUpinder Malhi 	}
293c7845bcaSUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
294c7845bcaSUpinder Malhi 
295c7845bcaSUpinder Malhi 	return NOTIFY_DONE;
296c7845bcaSUpinder Malhi }
297c7845bcaSUpinder Malhi static struct notifier_block usnic_ib_inetaddr_notifier = {
298c7845bcaSUpinder Malhi 	.notifier_call = usnic_ib_inetaddr_event
299c7845bcaSUpinder Malhi };
300c7845bcaSUpinder Malhi /* End of inet section*/
301c7845bcaSUpinder Malhi 
3027738613eSIra Weiny static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num,
3037738613eSIra Weiny 			        struct ib_port_immutable *immutable)
3047738613eSIra Weiny {
3057738613eSIra Weiny 	struct ib_port_attr attr;
3067738613eSIra Weiny 	int err;
3077738613eSIra Weiny 
308c4550c63SOr Gerlitz 	immutable->core_cap_flags = RDMA_CORE_PORT_USNIC;
309c4550c63SOr Gerlitz 
310c4550c63SOr Gerlitz 	err = ib_query_port(ibdev, port_num, &attr);
3117738613eSIra Weiny 	if (err)
3127738613eSIra Weiny 		return err;
3137738613eSIra Weiny 
3147738613eSIra Weiny 	immutable->pkey_tbl_len = attr.pkey_tbl_len;
3157738613eSIra Weiny 	immutable->gid_tbl_len = attr.gid_tbl_len;
3167738613eSIra Weiny 
3177738613eSIra Weiny 	return 0;
3187738613eSIra Weiny }
3197738613eSIra Weiny 
3209abb0d1bSLeon Romanovsky static void usnic_get_dev_fw_str(struct ib_device *device, char *str)
32115453e85SIra Weiny {
32215453e85SIra Weiny 	struct usnic_ib_dev *us_ibdev =
32315453e85SIra Weiny 		container_of(device, struct usnic_ib_dev, ib_dev);
32415453e85SIra Weiny 	struct ethtool_drvinfo info;
32515453e85SIra Weiny 
32615453e85SIra Weiny 	mutex_lock(&us_ibdev->usdev_lock);
32715453e85SIra Weiny 	us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
32815453e85SIra Weiny 	mutex_unlock(&us_ibdev->usdev_lock);
32915453e85SIra Weiny 
3309abb0d1bSLeon Romanovsky 	snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", info.fw_version);
33115453e85SIra Weiny }
33215453e85SIra Weiny 
333e7610581SKamal Heib static const struct ib_device_ops usnic_dev_ops = {
334e7610581SKamal Heib 	.alloc_pd = usnic_ib_alloc_pd,
335e7610581SKamal Heib 	.alloc_ucontext = usnic_ib_alloc_ucontext,
336e7610581SKamal Heib 	.create_ah = usnic_ib_create_ah,
337e7610581SKamal Heib 	.create_cq = usnic_ib_create_cq,
338e7610581SKamal Heib 	.create_qp = usnic_ib_create_qp,
339e7610581SKamal Heib 	.dealloc_pd = usnic_ib_dealloc_pd,
340e7610581SKamal Heib 	.dealloc_ucontext = usnic_ib_dealloc_ucontext,
341e7610581SKamal Heib 	.dereg_mr = usnic_ib_dereg_mr,
342e7610581SKamal Heib 	.destroy_ah = usnic_ib_destroy_ah,
343e7610581SKamal Heib 	.destroy_cq = usnic_ib_destroy_cq,
344e7610581SKamal Heib 	.destroy_qp = usnic_ib_destroy_qp,
345e7610581SKamal Heib 	.get_dev_fw_str = usnic_get_dev_fw_str,
346e7610581SKamal Heib 	.get_dma_mr = usnic_ib_get_dma_mr,
347e7610581SKamal Heib 	.get_link_layer = usnic_ib_port_link_layer,
348e7610581SKamal Heib 	.get_netdev = usnic_get_netdev,
349e7610581SKamal Heib 	.get_port_immutable = usnic_port_immutable,
350e7610581SKamal Heib 	.mmap = usnic_ib_mmap,
351e7610581SKamal Heib 	.modify_qp = usnic_ib_modify_qp,
352e7610581SKamal Heib 	.poll_cq = usnic_ib_poll_cq,
353e7610581SKamal Heib 	.post_recv = usnic_ib_post_recv,
354e7610581SKamal Heib 	.post_send = usnic_ib_post_send,
355e7610581SKamal Heib 	.query_device = usnic_ib_query_device,
356e7610581SKamal Heib 	.query_gid = usnic_ib_query_gid,
357e7610581SKamal Heib 	.query_pkey = usnic_ib_query_pkey,
358e7610581SKamal Heib 	.query_port = usnic_ib_query_port,
359e7610581SKamal Heib 	.query_qp = usnic_ib_query_qp,
360e7610581SKamal Heib 	.reg_user_mr = usnic_ib_reg_mr,
361e7610581SKamal Heib 	.req_notify_cq = usnic_ib_req_notify_cq,
362e7610581SKamal Heib };
363e7610581SKamal Heib 
364e3cf00d0SUpinder Malhi /* Start of PF discovery section */
365e3cf00d0SUpinder Malhi static void *usnic_ib_device_add(struct pci_dev *dev)
366e3cf00d0SUpinder Malhi {
367e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
368e3cf00d0SUpinder Malhi 	union ib_gid gid;
3695d50f400SLeon Romanovsky 	struct in_device *ind;
370c7845bcaSUpinder Malhi 	struct net_device *netdev;
371e3cf00d0SUpinder Malhi 
372e3cf00d0SUpinder Malhi 	usnic_dbg("\n");
373c7845bcaSUpinder Malhi 	netdev = pci_get_drvdata(dev);
374e3cf00d0SUpinder Malhi 
375*459cc69fSLeon Romanovsky 	us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev);
3762c79dad8SInsu Yun 	if (!us_ibdev) {
377e3cf00d0SUpinder Malhi 		usnic_err("Device %s context alloc failed\n",
378e3cf00d0SUpinder Malhi 				netdev_name(pci_get_drvdata(dev)));
3792c79dad8SInsu Yun 		return ERR_PTR(-EFAULT);
380e3cf00d0SUpinder Malhi 	}
381e3cf00d0SUpinder Malhi 
382e3cf00d0SUpinder Malhi 	us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);
3832c79dad8SInsu Yun 	if (!us_ibdev->ufdev) {
3842c79dad8SInsu Yun 		usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev));
385e3cf00d0SUpinder Malhi 		goto err_dealloc;
386e3cf00d0SUpinder Malhi 	}
387e3cf00d0SUpinder Malhi 
388e3cf00d0SUpinder Malhi 	mutex_init(&us_ibdev->usdev_lock);
389e3cf00d0SUpinder Malhi 	INIT_LIST_HEAD(&us_ibdev->vf_dev_list);
390e3cf00d0SUpinder Malhi 	INIT_LIST_HEAD(&us_ibdev->ctx_list);
391e3cf00d0SUpinder Malhi 
392e3cf00d0SUpinder Malhi 	us_ibdev->pdev = dev;
393e3cf00d0SUpinder Malhi 	us_ibdev->netdev = pci_get_drvdata(dev);
394e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.owner = THIS_MODULE;
39561f78268SUpinder Malhi 	us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP;
396e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT;
397e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS;
3986b06d52dSBart Van Assche 	us_ibdev->ib_dev.dev.parent = &dev->dev;
399e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION;
400e3cf00d0SUpinder Malhi 
401e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.uverbs_cmd_mask =
402e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
403e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
404e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
405e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
406e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
407e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_REG_MR) |
408e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_DEREG_MR) |
409e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
410e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
411e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
412e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_CREATE_QP) |
413e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
414e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_QUERY_QP) |
415e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
416e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
417e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
418e3cf00d0SUpinder Malhi 		(1ull << IB_USER_VERBS_CMD_OPEN_QP);
419e3cf00d0SUpinder Malhi 
420e7610581SKamal Heib 	ib_set_device_ops(&us_ibdev->ib_dev, &usnic_dev_ops);
421e3cf00d0SUpinder Malhi 
4220ede73bcSMatan Barak 	us_ibdev->ib_dev.driver_id = RDMA_DRIVER_USNIC;
423508a523fSParav Pandit 	rdma_set_device_sysfs_group(&us_ibdev->ib_dev, &usnic_attr_group);
424508a523fSParav Pandit 
425ea4baf7fSParav Pandit 	if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d"))
426e3cf00d0SUpinder Malhi 		goto err_fwd_dealloc;
427e3cf00d0SUpinder Malhi 
4288af94ac6SUpinder Malhi 	usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu);
4298af94ac6SUpinder Malhi 	usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr);
4308af94ac6SUpinder Malhi 	if (netif_carrier_ok(us_ibdev->netdev))
4318af94ac6SUpinder Malhi 		usnic_fwd_carrier_up(us_ibdev->ufdev);
4328af94ac6SUpinder Malhi 
4335d50f400SLeon Romanovsky 	ind = in_dev_get(netdev);
4345d50f400SLeon Romanovsky 	if (ind->ifa_list)
4355d50f400SLeon Romanovsky 		usnic_fwd_add_ipaddr(us_ibdev->ufdev,
4365d50f400SLeon Romanovsky 				     ind->ifa_list->ifa_address);
4375d50f400SLeon Romanovsky 	in_dev_put(ind);
438c7845bcaSUpinder Malhi 
439c7845bcaSUpinder Malhi 	usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,
440c7845bcaSUpinder Malhi 				us_ibdev->ufdev->inaddr, &gid.raw[0]);
441e3cf00d0SUpinder Malhi 	memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,
442e3cf00d0SUpinder Malhi 		sizeof(gid.global.interface_id));
443e3cf00d0SUpinder Malhi 	kref_init(&us_ibdev->vf_cnt);
444e3cf00d0SUpinder Malhi 
445e3cf00d0SUpinder Malhi 	usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n",
4469de69861SJason Gunthorpe 		   dev_name(&us_ibdev->ib_dev.dev),
4479de69861SJason Gunthorpe 		   netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac,
4489de69861SJason Gunthorpe 		   us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu);
449e3cf00d0SUpinder Malhi 	return us_ibdev;
450e3cf00d0SUpinder Malhi 
451e3cf00d0SUpinder Malhi err_fwd_dealloc:
452e3cf00d0SUpinder Malhi 	usnic_fwd_dev_free(us_ibdev->ufdev);
453e3cf00d0SUpinder Malhi err_dealloc:
454e3cf00d0SUpinder Malhi 	usnic_err("failed -- deallocing device\n");
455e3cf00d0SUpinder Malhi 	ib_dealloc_device(&us_ibdev->ib_dev);
456e3cf00d0SUpinder Malhi 	return NULL;
457e3cf00d0SUpinder Malhi }
458e3cf00d0SUpinder Malhi 
459e3cf00d0SUpinder Malhi static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev)
460e3cf00d0SUpinder Malhi {
4619de69861SJason Gunthorpe 	usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev));
462e3cf00d0SUpinder Malhi 	usnic_ib_sysfs_unregister_usdev(us_ibdev);
463e3cf00d0SUpinder Malhi 	usnic_fwd_dev_free(us_ibdev->ufdev);
464e3cf00d0SUpinder Malhi 	ib_unregister_device(&us_ibdev->ib_dev);
465e3cf00d0SUpinder Malhi 	ib_dealloc_device(&us_ibdev->ib_dev);
466e3cf00d0SUpinder Malhi }
467e3cf00d0SUpinder Malhi 
468e3cf00d0SUpinder Malhi static void usnic_ib_undiscover_pf(struct kref *kref)
469e3cf00d0SUpinder Malhi {
470e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev, *tmp;
471e3cf00d0SUpinder Malhi 	struct pci_dev *dev;
472e3cf00d0SUpinder Malhi 	bool found = false;
473e3cf00d0SUpinder Malhi 
474e3cf00d0SUpinder Malhi 	dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev;
475e3cf00d0SUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
476e3cf00d0SUpinder Malhi 	list_for_each_entry_safe(us_ibdev, tmp,
477e3cf00d0SUpinder Malhi 				&usnic_ib_ibdev_list, ib_dev_link) {
478e3cf00d0SUpinder Malhi 		if (us_ibdev->pdev == dev) {
479e3cf00d0SUpinder Malhi 			list_del(&us_ibdev->ib_dev_link);
480e3cf00d0SUpinder Malhi 			usnic_ib_device_remove(us_ibdev);
481e3cf00d0SUpinder Malhi 			found = true;
482e3cf00d0SUpinder Malhi 			break;
483e3cf00d0SUpinder Malhi 		}
484e3cf00d0SUpinder Malhi 	}
485e3cf00d0SUpinder Malhi 
486e3cf00d0SUpinder Malhi 	WARN(!found, "Failed to remove PF %s\n", pci_name(dev));
487e3cf00d0SUpinder Malhi 
488e3cf00d0SUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
489e3cf00d0SUpinder Malhi }
490e3cf00d0SUpinder Malhi 
491e3cf00d0SUpinder Malhi static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic)
492e3cf00d0SUpinder Malhi {
493e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
494e3cf00d0SUpinder Malhi 	struct pci_dev *parent_pci, *vf_pci;
495e3cf00d0SUpinder Malhi 	int err;
496e3cf00d0SUpinder Malhi 
497e3cf00d0SUpinder Malhi 	vf_pci = usnic_vnic_get_pdev(vnic);
498e3cf00d0SUpinder Malhi 	parent_pci = pci_physfn(vf_pci);
499e3cf00d0SUpinder Malhi 
500e3cf00d0SUpinder Malhi 	BUG_ON(!parent_pci);
501e3cf00d0SUpinder Malhi 
502e3cf00d0SUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
503e3cf00d0SUpinder Malhi 	list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
504e3cf00d0SUpinder Malhi 		if (us_ibdev->pdev == parent_pci) {
505e3cf00d0SUpinder Malhi 			kref_get(&us_ibdev->vf_cnt);
506e3cf00d0SUpinder Malhi 			goto out;
507e3cf00d0SUpinder Malhi 		}
508e3cf00d0SUpinder Malhi 	}
509e3cf00d0SUpinder Malhi 
510e3cf00d0SUpinder Malhi 	us_ibdev = usnic_ib_device_add(parent_pci);
511e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(us_ibdev)) {
5126a54d9f9SUpinder Malhi 		us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT);
513e3cf00d0SUpinder Malhi 		goto out;
514e3cf00d0SUpinder Malhi 	}
515e3cf00d0SUpinder Malhi 
516e3cf00d0SUpinder Malhi 	err = usnic_ib_sysfs_register_usdev(us_ibdev);
517e3cf00d0SUpinder Malhi 	if (err) {
518e3cf00d0SUpinder Malhi 		usnic_ib_device_remove(us_ibdev);
519e3cf00d0SUpinder Malhi 		us_ibdev = ERR_PTR(err);
520e3cf00d0SUpinder Malhi 		goto out;
521e3cf00d0SUpinder Malhi 	}
522e3cf00d0SUpinder Malhi 
523e3cf00d0SUpinder Malhi 	list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list);
524e3cf00d0SUpinder Malhi out:
525e3cf00d0SUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
526e3cf00d0SUpinder Malhi 	return us_ibdev;
527e3cf00d0SUpinder Malhi }
528e3cf00d0SUpinder Malhi /* End of PF discovery section */
529e3cf00d0SUpinder Malhi 
530e3cf00d0SUpinder Malhi /* Start of PCI section */
531e3cf00d0SUpinder Malhi 
5329baa3c34SBenoit Taine static const struct pci_device_id usnic_ib_pci_ids[] = {
533e3cf00d0SUpinder Malhi 	{PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
534e3cf00d0SUpinder Malhi 	{0,}
535e3cf00d0SUpinder Malhi };
536e3cf00d0SUpinder Malhi 
537e3cf00d0SUpinder Malhi static int usnic_ib_pci_probe(struct pci_dev *pdev,
538e3cf00d0SUpinder Malhi 				const struct pci_device_id *id)
539e3cf00d0SUpinder Malhi {
540e3cf00d0SUpinder Malhi 	int err;
541e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *pf;
542e3cf00d0SUpinder Malhi 	struct usnic_ib_vf *vf;
543e3cf00d0SUpinder Malhi 	enum usnic_vnic_res_type res_type;
544e3cf00d0SUpinder Malhi 
545e3cf00d0SUpinder Malhi 	vf = kzalloc(sizeof(*vf), GFP_KERNEL);
546e3cf00d0SUpinder Malhi 	if (!vf)
547e3cf00d0SUpinder Malhi 		return -ENOMEM;
548e3cf00d0SUpinder Malhi 
549e3cf00d0SUpinder Malhi 	err = pci_enable_device(pdev);
550e3cf00d0SUpinder Malhi 	if (err) {
551e3cf00d0SUpinder Malhi 		usnic_err("Failed to enable %s with err %d\n",
552e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
553e3cf00d0SUpinder Malhi 		goto out_clean_vf;
554e3cf00d0SUpinder Malhi 	}
555e3cf00d0SUpinder Malhi 
556e3cf00d0SUpinder Malhi 	err = pci_request_regions(pdev, DRV_NAME);
557e3cf00d0SUpinder Malhi 	if (err) {
558e3cf00d0SUpinder Malhi 		usnic_err("Failed to request region for %s with err %d\n",
559e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
560e3cf00d0SUpinder Malhi 		goto out_disable_device;
561e3cf00d0SUpinder Malhi 	}
562e3cf00d0SUpinder Malhi 
563e3cf00d0SUpinder Malhi 	pci_set_master(pdev);
564e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, vf);
565e3cf00d0SUpinder Malhi 
566e3cf00d0SUpinder Malhi 	vf->vnic = usnic_vnic_alloc(pdev);
567e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(vf->vnic)) {
5686a54d9f9SUpinder Malhi 		err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM;
569e3cf00d0SUpinder Malhi 		usnic_err("Failed to alloc vnic for %s with err %d\n",
570e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
571e3cf00d0SUpinder Malhi 		goto out_release_regions;
572e3cf00d0SUpinder Malhi 	}
573e3cf00d0SUpinder Malhi 
574e3cf00d0SUpinder Malhi 	pf = usnic_ib_discover_pf(vf->vnic);
575e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(pf)) {
576e3cf00d0SUpinder Malhi 		usnic_err("Failed to discover pf of vnic %s with err%ld\n",
577e3cf00d0SUpinder Malhi 				pci_name(pdev), PTR_ERR(pf));
5786a54d9f9SUpinder Malhi 		err = pf ? PTR_ERR(pf) : -EFAULT;
579e3cf00d0SUpinder Malhi 		goto out_clean_vnic;
580e3cf00d0SUpinder Malhi 	}
581e3cf00d0SUpinder Malhi 
582e3cf00d0SUpinder Malhi 	vf->pf = pf;
583e3cf00d0SUpinder Malhi 	spin_lock_init(&vf->lock);
584e3cf00d0SUpinder Malhi 	mutex_lock(&pf->usdev_lock);
585e3cf00d0SUpinder Malhi 	list_add_tail(&vf->link, &pf->vf_dev_list);
586e3cf00d0SUpinder Malhi 	/*
587e3cf00d0SUpinder Malhi 	 * Save max settings (will be same for each VF, easier to re-write than
588e3cf00d0SUpinder Malhi 	 * to say "if (!set) { set_values(); set=1; }
589e3cf00d0SUpinder Malhi 	 */
590e3cf00d0SUpinder Malhi 	for (res_type = USNIC_VNIC_RES_TYPE_EOL+1;
591e3cf00d0SUpinder Malhi 			res_type < USNIC_VNIC_RES_TYPE_MAX;
592e3cf00d0SUpinder Malhi 			res_type++) {
593e3cf00d0SUpinder Malhi 		pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic,
594e3cf00d0SUpinder Malhi 								res_type);
595e3cf00d0SUpinder Malhi 	}
596e3cf00d0SUpinder Malhi 
597e3cf00d0SUpinder Malhi 	mutex_unlock(&pf->usdev_lock);
598e3cf00d0SUpinder Malhi 
599e3cf00d0SUpinder Malhi 	usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev),
6009de69861SJason Gunthorpe 		   dev_name(&pf->ib_dev.dev));
601e3cf00d0SUpinder Malhi 	usnic_ib_log_vf(vf);
602e3cf00d0SUpinder Malhi 	return 0;
603e3cf00d0SUpinder Malhi 
604e3cf00d0SUpinder Malhi out_clean_vnic:
605e3cf00d0SUpinder Malhi 	usnic_vnic_free(vf->vnic);
606e3cf00d0SUpinder Malhi out_release_regions:
607e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, NULL);
608e3cf00d0SUpinder Malhi 	pci_clear_master(pdev);
609e3cf00d0SUpinder Malhi 	pci_release_regions(pdev);
610e3cf00d0SUpinder Malhi out_disable_device:
611e3cf00d0SUpinder Malhi 	pci_disable_device(pdev);
612e3cf00d0SUpinder Malhi out_clean_vf:
613e3cf00d0SUpinder Malhi 	kfree(vf);
614e3cf00d0SUpinder Malhi 	return err;
615e3cf00d0SUpinder Malhi }
616e3cf00d0SUpinder Malhi 
617e3cf00d0SUpinder Malhi static void usnic_ib_pci_remove(struct pci_dev *pdev)
618e3cf00d0SUpinder Malhi {
619e3cf00d0SUpinder Malhi 	struct usnic_ib_vf *vf = pci_get_drvdata(pdev);
620e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *pf = vf->pf;
621e3cf00d0SUpinder Malhi 
622e3cf00d0SUpinder Malhi 	mutex_lock(&pf->usdev_lock);
623e3cf00d0SUpinder Malhi 	list_del(&vf->link);
624e3cf00d0SUpinder Malhi 	mutex_unlock(&pf->usdev_lock);
625e3cf00d0SUpinder Malhi 
626e3cf00d0SUpinder Malhi 	kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf);
627e3cf00d0SUpinder Malhi 	usnic_vnic_free(vf->vnic);
628e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, NULL);
629e3cf00d0SUpinder Malhi 	pci_clear_master(pdev);
630e3cf00d0SUpinder Malhi 	pci_release_regions(pdev);
631e3cf00d0SUpinder Malhi 	pci_disable_device(pdev);
632e3cf00d0SUpinder Malhi 	kfree(vf);
633e3cf00d0SUpinder Malhi 
634e3cf00d0SUpinder Malhi 	usnic_info("Removed VF %s\n", pci_name(pdev));
635e3cf00d0SUpinder Malhi }
636e3cf00d0SUpinder Malhi 
637e3cf00d0SUpinder Malhi /* PCI driver entry points */
638e3cf00d0SUpinder Malhi static struct pci_driver usnic_ib_pci_driver = {
639e3cf00d0SUpinder Malhi 	.name = DRV_NAME,
640e3cf00d0SUpinder Malhi 	.id_table = usnic_ib_pci_ids,
641e3cf00d0SUpinder Malhi 	.probe = usnic_ib_pci_probe,
642e3cf00d0SUpinder Malhi 	.remove = usnic_ib_pci_remove,
643e3cf00d0SUpinder Malhi };
644e3cf00d0SUpinder Malhi /* End of PCI section */
645e3cf00d0SUpinder Malhi 
646e3cf00d0SUpinder Malhi /* Start of module section */
647e3cf00d0SUpinder Malhi static int __init usnic_ib_init(void)
648e3cf00d0SUpinder Malhi {
649e3cf00d0SUpinder Malhi 	int err;
650e3cf00d0SUpinder Malhi 
651e3cf00d0SUpinder Malhi 	printk_once(KERN_INFO "%s", usnic_version);
652e3cf00d0SUpinder Malhi 
653e3cf00d0SUpinder Malhi 	err = usnic_uiom_init(DRV_NAME);
654e3cf00d0SUpinder Malhi 	if (err) {
655901018f2SColin Ian King 		usnic_err("Unable to initialize umem with err %d\n", err);
656e3cf00d0SUpinder Malhi 		return err;
657e3cf00d0SUpinder Malhi 	}
658e3cf00d0SUpinder Malhi 
65986cd747cSChristophe Jaillet 	err = pci_register_driver(&usnic_ib_pci_driver);
66086cd747cSChristophe Jaillet 	if (err) {
661e3cf00d0SUpinder Malhi 		usnic_err("Unable to register with PCI\n");
662e3cf00d0SUpinder Malhi 		goto out_umem_fini;
663e3cf00d0SUpinder Malhi 	}
664e3cf00d0SUpinder Malhi 
665e3cf00d0SUpinder Malhi 	err = register_netdevice_notifier(&usnic_ib_netdevice_notifier);
666e3cf00d0SUpinder Malhi 	if (err) {
667e3cf00d0SUpinder Malhi 		usnic_err("Failed to register netdev notifier\n");
668e3cf00d0SUpinder Malhi 		goto out_pci_unreg;
669e3cf00d0SUpinder Malhi 	}
670e3cf00d0SUpinder Malhi 
671c7845bcaSUpinder Malhi 	err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
672c7845bcaSUpinder Malhi 	if (err) {
673c7845bcaSUpinder Malhi 		usnic_err("Failed to register inet addr notifier\n");
674c7845bcaSUpinder Malhi 		goto out_unreg_netdev_notifier;
675c7845bcaSUpinder Malhi 	}
676c7845bcaSUpinder Malhi 
677e3cf00d0SUpinder Malhi 	err = usnic_transport_init();
678e3cf00d0SUpinder Malhi 	if (err) {
679e3cf00d0SUpinder Malhi 		usnic_err("Failed to initialize transport\n");
680c7845bcaSUpinder Malhi 		goto out_unreg_inetaddr_notifier;
681e3cf00d0SUpinder Malhi 	}
682e3cf00d0SUpinder Malhi 
683e3cf00d0SUpinder Malhi 	usnic_debugfs_init();
684e3cf00d0SUpinder Malhi 
685e3cf00d0SUpinder Malhi 	return 0;
686e3cf00d0SUpinder Malhi 
687c7845bcaSUpinder Malhi out_unreg_inetaddr_notifier:
688c7845bcaSUpinder Malhi 	unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
689e3cf00d0SUpinder Malhi out_unreg_netdev_notifier:
690e3cf00d0SUpinder Malhi 	unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
691e3cf00d0SUpinder Malhi out_pci_unreg:
692e3cf00d0SUpinder Malhi 	pci_unregister_driver(&usnic_ib_pci_driver);
693e3cf00d0SUpinder Malhi out_umem_fini:
694e3cf00d0SUpinder Malhi 	usnic_uiom_fini();
695e3cf00d0SUpinder Malhi 
696e3cf00d0SUpinder Malhi 	return err;
697e3cf00d0SUpinder Malhi }
698e3cf00d0SUpinder Malhi 
699e3cf00d0SUpinder Malhi static void __exit usnic_ib_destroy(void)
700e3cf00d0SUpinder Malhi {
701e3cf00d0SUpinder Malhi 	usnic_dbg("\n");
702e3cf00d0SUpinder Malhi 	usnic_debugfs_exit();
703e3cf00d0SUpinder Malhi 	usnic_transport_fini();
704c7845bcaSUpinder Malhi 	unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
705e3cf00d0SUpinder Malhi 	unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
706e3cf00d0SUpinder Malhi 	pci_unregister_driver(&usnic_ib_pci_driver);
707e3cf00d0SUpinder Malhi 	usnic_uiom_fini();
708e3cf00d0SUpinder Malhi }
709e3cf00d0SUpinder Malhi 
710e3cf00d0SUpinder Malhi MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver");
711e3cf00d0SUpinder Malhi MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>");
712e3cf00d0SUpinder Malhi MODULE_LICENSE("Dual BSD/GPL");
713e3cf00d0SUpinder Malhi module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR);
714e3cf00d0SUpinder Malhi module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR);
715e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3");
716e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs");
717e3cf00d0SUpinder Malhi MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids);
718e3cf00d0SUpinder Malhi 
719e3cf00d0SUpinder Malhi module_init(usnic_ib_init);
720e3cf00d0SUpinder Malhi module_exit(usnic_ib_destroy);
721e3cf00d0SUpinder Malhi /* End of module section */
722