xref: /linux/drivers/infiniband/hw/usnic/usnic_ib_main.c (revision 4f6b838c378a52ea3ae0b15f12ca8a20849072fa)
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 {
922ac5a6d3SArnd Bergmann 	char *buf = kzalloc(1000, GFP_KERNEL);
932ac5a6d3SArnd Bergmann 
942ac5a6d3SArnd Bergmann 	if (!buf)
952ac5a6d3SArnd Bergmann 		return;
962ac5a6d3SArnd Bergmann 
972ac5a6d3SArnd Bergmann 	usnic_ib_dump_vf(vf, buf, 1000);
98e3cf00d0SUpinder Malhi 	usnic_dbg("%s\n", buf);
992ac5a6d3SArnd Bergmann 
1002ac5a6d3SArnd Bergmann 	kfree(buf);
101e3cf00d0SUpinder Malhi }
102e3cf00d0SUpinder Malhi 
103e3cf00d0SUpinder Malhi /* Start of netdev section */
104e3cf00d0SUpinder Malhi static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev)
105e3cf00d0SUpinder Malhi {
106e3cf00d0SUpinder Malhi 	struct usnic_ib_ucontext *ctx;
107e3cf00d0SUpinder Malhi 	struct usnic_ib_qp_grp *qp_grp;
108e3cf00d0SUpinder Malhi 	enum ib_qp_state cur_state;
109e3cf00d0SUpinder Malhi 	int status;
110e3cf00d0SUpinder Malhi 
111e3cf00d0SUpinder Malhi 	BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
112e3cf00d0SUpinder Malhi 
113e3cf00d0SUpinder Malhi 	list_for_each_entry(ctx, &us_ibdev->ctx_list, link) {
114e3cf00d0SUpinder Malhi 		list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) {
115e3cf00d0SUpinder Malhi 			cur_state = qp_grp->state;
116e3cf00d0SUpinder Malhi 			if (cur_state == IB_QPS_INIT ||
117e3cf00d0SUpinder Malhi 				cur_state == IB_QPS_RTR ||
118e3cf00d0SUpinder Malhi 				cur_state == IB_QPS_RTS) {
119e3cf00d0SUpinder Malhi 				status = usnic_ib_qp_grp_modify(qp_grp,
120e3cf00d0SUpinder Malhi 								IB_QPS_ERR,
121e3cf00d0SUpinder Malhi 								NULL);
122e3cf00d0SUpinder Malhi 				if (status) {
123dfd022a9SColin Ian King 					usnic_err("Failed to transition qp grp %u from %s to %s\n",
124e3cf00d0SUpinder Malhi 						qp_grp->grp_id,
125e3cf00d0SUpinder Malhi 						usnic_ib_qp_grp_state_to_string
126e3cf00d0SUpinder Malhi 						(cur_state),
127e3cf00d0SUpinder Malhi 						usnic_ib_qp_grp_state_to_string
128e3cf00d0SUpinder Malhi 						(IB_QPS_ERR));
129e3cf00d0SUpinder Malhi 				}
130e3cf00d0SUpinder Malhi 			}
131e3cf00d0SUpinder Malhi 		}
132e3cf00d0SUpinder Malhi 	}
133e3cf00d0SUpinder Malhi }
134e3cf00d0SUpinder Malhi 
135e3cf00d0SUpinder Malhi static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev,
136e3cf00d0SUpinder Malhi 					unsigned long event)
137e3cf00d0SUpinder Malhi {
138e3cf00d0SUpinder Malhi 	struct net_device *netdev;
139e3cf00d0SUpinder Malhi 	struct ib_event ib_event;
140e3cf00d0SUpinder Malhi 
141e3cf00d0SUpinder Malhi 	memset(&ib_event, 0, sizeof(ib_event));
142e3cf00d0SUpinder Malhi 
143e3cf00d0SUpinder Malhi 	mutex_lock(&us_ibdev->usdev_lock);
144e3cf00d0SUpinder Malhi 	netdev = us_ibdev->netdev;
145e3cf00d0SUpinder Malhi 	switch (event) {
146e3cf00d0SUpinder Malhi 	case NETDEV_REBOOT:
1479de69861SJason Gunthorpe 		usnic_info("PF Reset on %s\n", dev_name(&us_ibdev->ib_dev.dev));
148e3cf00d0SUpinder Malhi 		usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
149e3cf00d0SUpinder Malhi 		ib_event.event = IB_EVENT_PORT_ERR;
150e3cf00d0SUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
151e3cf00d0SUpinder Malhi 		ib_event.element.port_num = 1;
152e3cf00d0SUpinder Malhi 		ib_dispatch_event(&ib_event);
153e3cf00d0SUpinder Malhi 		break;
154e3cf00d0SUpinder Malhi 	case NETDEV_UP:
155e3cf00d0SUpinder Malhi 	case NETDEV_DOWN:
156e3cf00d0SUpinder Malhi 	case NETDEV_CHANGE:
1578af94ac6SUpinder Malhi 		if (!us_ibdev->ufdev->link_up &&
1588af94ac6SUpinder Malhi 				netif_carrier_ok(netdev)) {
1598af94ac6SUpinder Malhi 			usnic_fwd_carrier_up(us_ibdev->ufdev);
1609de69861SJason Gunthorpe 			usnic_info("Link UP on %s\n",
1619de69861SJason Gunthorpe 				   dev_name(&us_ibdev->ib_dev.dev));
162e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_PORT_ACTIVE;
163e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
164e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
165e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
1668af94ac6SUpinder Malhi 		} else if (us_ibdev->ufdev->link_up &&
1678af94ac6SUpinder Malhi 				!netif_carrier_ok(netdev)) {
1688af94ac6SUpinder Malhi 			usnic_fwd_carrier_down(us_ibdev->ufdev);
1699de69861SJason Gunthorpe 			usnic_info("Link DOWN on %s\n",
1709de69861SJason Gunthorpe 				   dev_name(&us_ibdev->ib_dev.dev));
171e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
172e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_PORT_ERR;
173e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
174e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
175e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
176e3cf00d0SUpinder Malhi 		} else {
177c30392abSRoland Dreier 			usnic_dbg("Ignoring %s on %s\n",
1783e0c2dbfSKirill Tkhai 					netdev_cmd_to_name(event),
1799de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev));
180e3cf00d0SUpinder Malhi 		}
181e3cf00d0SUpinder Malhi 		break;
182e3cf00d0SUpinder Malhi 	case NETDEV_CHANGEADDR:
1838af94ac6SUpinder Malhi 		if (!memcmp(us_ibdev->ufdev->mac, netdev->dev_addr,
1848af94ac6SUpinder Malhi 				sizeof(us_ibdev->ufdev->mac))) {
185c30392abSRoland Dreier 			usnic_dbg("Ignoring addr change on %s\n",
1869de69861SJason Gunthorpe 				  dev_name(&us_ibdev->ib_dev.dev));
187e3cf00d0SUpinder Malhi 		} else {
188e3cf00d0SUpinder Malhi 			usnic_info(" %s old mac: %pM new mac: %pM\n",
1899de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev),
1908af94ac6SUpinder Malhi 					us_ibdev->ufdev->mac,
191e3cf00d0SUpinder Malhi 					netdev->dev_addr);
1928af94ac6SUpinder Malhi 			usnic_fwd_set_mac(us_ibdev->ufdev, netdev->dev_addr);
193e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
194e3cf00d0SUpinder Malhi 			ib_event.event = IB_EVENT_GID_CHANGE;
195e3cf00d0SUpinder Malhi 			ib_event.device = &us_ibdev->ib_dev;
196e3cf00d0SUpinder Malhi 			ib_event.element.port_num = 1;
197e3cf00d0SUpinder Malhi 			ib_dispatch_event(&ib_event);
198e3cf00d0SUpinder Malhi 		}
199e3cf00d0SUpinder Malhi 
200e3cf00d0SUpinder Malhi 		break;
201e3cf00d0SUpinder Malhi 	case NETDEV_CHANGEMTU:
2028af94ac6SUpinder Malhi 		if (us_ibdev->ufdev->mtu != netdev->mtu) {
203e3cf00d0SUpinder Malhi 			usnic_info("MTU Change on %s old: %u new: %u\n",
2049de69861SJason Gunthorpe 					dev_name(&us_ibdev->ib_dev.dev),
2058af94ac6SUpinder Malhi 					us_ibdev->ufdev->mtu, netdev->mtu);
2068af94ac6SUpinder Malhi 			usnic_fwd_set_mtu(us_ibdev->ufdev, netdev->mtu);
207e3cf00d0SUpinder Malhi 			usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
208e3cf00d0SUpinder Malhi 		} else {
209e3cf00d0SUpinder Malhi 			usnic_dbg("Ignoring MTU change on %s\n",
2109de69861SJason Gunthorpe 				  dev_name(&us_ibdev->ib_dev.dev));
211e3cf00d0SUpinder Malhi 		}
212e3cf00d0SUpinder Malhi 		break;
213e3cf00d0SUpinder Malhi 	default:
214c30392abSRoland Dreier 		usnic_dbg("Ignoring event %s on %s",
2153e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
2169de69861SJason Gunthorpe 				dev_name(&us_ibdev->ib_dev.dev));
217e3cf00d0SUpinder Malhi 	}
218e3cf00d0SUpinder Malhi 	mutex_unlock(&us_ibdev->usdev_lock);
219e3cf00d0SUpinder Malhi }
220e3cf00d0SUpinder Malhi 
221e3cf00d0SUpinder Malhi static int usnic_ib_netdevice_event(struct notifier_block *notifier,
222e3cf00d0SUpinder Malhi 					unsigned long event, void *ptr)
223e3cf00d0SUpinder Malhi {
224e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
2255bb3c1e9SParvi Kaustubhi 	struct ib_device *ibdev;
226e3cf00d0SUpinder Malhi 
227e3cf00d0SUpinder Malhi 	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
228e3cf00d0SUpinder Malhi 
2295bb3c1e9SParvi Kaustubhi 	ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC);
2305bb3c1e9SParvi Kaustubhi 	if (!ibdev)
2315bb3c1e9SParvi Kaustubhi 		return NOTIFY_DONE;
232e3cf00d0SUpinder Malhi 
2335bb3c1e9SParvi Kaustubhi 	us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev);
2345bb3c1e9SParvi Kaustubhi 	usnic_ib_handle_usdev_event(us_ibdev, event);
2355bb3c1e9SParvi Kaustubhi 	ib_device_put(ibdev);
236e3cf00d0SUpinder Malhi 	return NOTIFY_DONE;
237e3cf00d0SUpinder Malhi }
238e3cf00d0SUpinder Malhi 
239e3cf00d0SUpinder Malhi static struct notifier_block usnic_ib_netdevice_notifier = {
240e3cf00d0SUpinder Malhi 	.notifier_call = usnic_ib_netdevice_event
241e3cf00d0SUpinder Malhi };
242e3cf00d0SUpinder Malhi /* End of netdev section */
243e3cf00d0SUpinder Malhi 
244c7845bcaSUpinder Malhi /* Start of inet section */
245c7845bcaSUpinder Malhi static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev,
246c7845bcaSUpinder Malhi 					unsigned long event, void *ptr)
247c7845bcaSUpinder Malhi {
248c7845bcaSUpinder Malhi 	struct in_ifaddr *ifa = ptr;
249c7845bcaSUpinder Malhi 	struct ib_event ib_event;
250c7845bcaSUpinder Malhi 
251c7845bcaSUpinder Malhi 	mutex_lock(&us_ibdev->usdev_lock);
252c7845bcaSUpinder Malhi 
253c7845bcaSUpinder Malhi 	switch (event) {
254c7845bcaSUpinder Malhi 	case NETDEV_DOWN:
255c7845bcaSUpinder Malhi 		usnic_info("%s via ip notifiers",
2563e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event));
257c7845bcaSUpinder Malhi 		usnic_fwd_del_ipaddr(us_ibdev->ufdev);
258c7845bcaSUpinder Malhi 		usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
259c7845bcaSUpinder Malhi 		ib_event.event = IB_EVENT_GID_CHANGE;
260c7845bcaSUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
261c7845bcaSUpinder Malhi 		ib_event.element.port_num = 1;
262c7845bcaSUpinder Malhi 		ib_dispatch_event(&ib_event);
263c7845bcaSUpinder Malhi 		break;
264c7845bcaSUpinder Malhi 	case NETDEV_UP:
265c7845bcaSUpinder Malhi 		usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
266c7845bcaSUpinder Malhi 		usnic_info("%s via ip notifiers: ip %pI4",
2673e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
268c7845bcaSUpinder Malhi 				&us_ibdev->ufdev->inaddr);
269c7845bcaSUpinder Malhi 		ib_event.event = IB_EVENT_GID_CHANGE;
270c7845bcaSUpinder Malhi 		ib_event.device = &us_ibdev->ib_dev;
271c7845bcaSUpinder Malhi 		ib_event.element.port_num = 1;
272c7845bcaSUpinder Malhi 		ib_dispatch_event(&ib_event);
273c7845bcaSUpinder Malhi 		break;
274c7845bcaSUpinder Malhi 	default:
275c30392abSRoland Dreier 		usnic_info("Ignoring event %s on %s",
2763e0c2dbfSKirill Tkhai 				netdev_cmd_to_name(event),
2779de69861SJason Gunthorpe 				dev_name(&us_ibdev->ib_dev.dev));
278c7845bcaSUpinder Malhi 	}
279c7845bcaSUpinder Malhi 	mutex_unlock(&us_ibdev->usdev_lock);
280c7845bcaSUpinder Malhi 
281c7845bcaSUpinder Malhi 	return NOTIFY_DONE;
282c7845bcaSUpinder Malhi }
283c7845bcaSUpinder Malhi 
284c7845bcaSUpinder Malhi static int usnic_ib_inetaddr_event(struct notifier_block *notifier,
285c7845bcaSUpinder Malhi 					unsigned long event, void *ptr)
286c7845bcaSUpinder Malhi {
287c7845bcaSUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
288c7845bcaSUpinder Malhi 	struct in_ifaddr *ifa = ptr;
289c7845bcaSUpinder Malhi 	struct net_device *netdev = ifa->ifa_dev->dev;
2905bb3c1e9SParvi Kaustubhi 	struct ib_device *ibdev;
291c7845bcaSUpinder Malhi 
2925bb3c1e9SParvi Kaustubhi 	ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC);
2935bb3c1e9SParvi Kaustubhi 	if (!ibdev)
2945bb3c1e9SParvi Kaustubhi 		return NOTIFY_DONE;
2955bb3c1e9SParvi Kaustubhi 
2965bb3c1e9SParvi Kaustubhi 	us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev);
297c7845bcaSUpinder Malhi 	usnic_ib_handle_inet_event(us_ibdev, event, ptr);
2985bb3c1e9SParvi Kaustubhi 	ib_device_put(ibdev);
299c7845bcaSUpinder Malhi 	return NOTIFY_DONE;
300c7845bcaSUpinder Malhi }
301c7845bcaSUpinder Malhi static struct notifier_block usnic_ib_inetaddr_notifier = {
302c7845bcaSUpinder Malhi 	.notifier_call = usnic_ib_inetaddr_event
303c7845bcaSUpinder Malhi };
304c7845bcaSUpinder Malhi /* End of inet section*/
305c7845bcaSUpinder Malhi 
3067738613eSIra Weiny static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num,
3077738613eSIra Weiny 			        struct ib_port_immutable *immutable)
3087738613eSIra Weiny {
3097738613eSIra Weiny 	struct ib_port_attr attr;
3107738613eSIra Weiny 	int err;
3117738613eSIra Weiny 
312c4550c63SOr Gerlitz 	immutable->core_cap_flags = RDMA_CORE_PORT_USNIC;
313c4550c63SOr Gerlitz 
314c4550c63SOr Gerlitz 	err = ib_query_port(ibdev, port_num, &attr);
3157738613eSIra Weiny 	if (err)
3167738613eSIra Weiny 		return err;
3177738613eSIra Weiny 
3187738613eSIra Weiny 	immutable->gid_tbl_len = attr.gid_tbl_len;
3197738613eSIra Weiny 
3207738613eSIra Weiny 	return 0;
3217738613eSIra Weiny }
3227738613eSIra Weiny 
3239abb0d1bSLeon Romanovsky static void usnic_get_dev_fw_str(struct ib_device *device, char *str)
32415453e85SIra Weiny {
32515453e85SIra Weiny 	struct usnic_ib_dev *us_ibdev =
32615453e85SIra Weiny 		container_of(device, struct usnic_ib_dev, ib_dev);
32715453e85SIra Weiny 	struct ethtool_drvinfo info;
32815453e85SIra Weiny 
32915453e85SIra Weiny 	mutex_lock(&us_ibdev->usdev_lock);
33015453e85SIra Weiny 	us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
33115453e85SIra Weiny 	mutex_unlock(&us_ibdev->usdev_lock);
33215453e85SIra Weiny 
3339abb0d1bSLeon Romanovsky 	snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", info.fw_version);
33415453e85SIra Weiny }
33515453e85SIra Weiny 
336e7610581SKamal Heib static const struct ib_device_ops usnic_dev_ops = {
3377a154142SJason Gunthorpe 	.owner = THIS_MODULE,
338b9560a41SJason Gunthorpe 	.driver_id = RDMA_DRIVER_USNIC,
33972c6ec18SJason Gunthorpe 	.uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION,
340b9560a41SJason Gunthorpe 
341e7610581SKamal Heib 	.alloc_pd = usnic_ib_alloc_pd,
342e7610581SKamal Heib 	.alloc_ucontext = usnic_ib_alloc_ucontext,
343e7610581SKamal Heib 	.create_cq = usnic_ib_create_cq,
344e7610581SKamal Heib 	.create_qp = usnic_ib_create_qp,
345e7610581SKamal Heib 	.dealloc_pd = usnic_ib_dealloc_pd,
346e7610581SKamal Heib 	.dealloc_ucontext = usnic_ib_dealloc_ucontext,
347e7610581SKamal Heib 	.dereg_mr = usnic_ib_dereg_mr,
348e7610581SKamal Heib 	.destroy_cq = usnic_ib_destroy_cq,
349e7610581SKamal Heib 	.destroy_qp = usnic_ib_destroy_qp,
350e7610581SKamal Heib 	.get_dev_fw_str = usnic_get_dev_fw_str,
351e7610581SKamal Heib 	.get_link_layer = usnic_ib_port_link_layer,
352e7610581SKamal Heib 	.get_port_immutable = usnic_port_immutable,
353e7610581SKamal Heib 	.mmap = usnic_ib_mmap,
354e7610581SKamal Heib 	.modify_qp = usnic_ib_modify_qp,
355e7610581SKamal Heib 	.query_device = usnic_ib_query_device,
356e7610581SKamal Heib 	.query_gid = usnic_ib_query_gid,
357e7610581SKamal Heib 	.query_port = usnic_ib_query_port,
358e7610581SKamal Heib 	.query_qp = usnic_ib_query_qp,
359e7610581SKamal Heib 	.reg_user_mr = usnic_ib_reg_mr,
36021a428a0SLeon Romanovsky 	INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),
361e39afe3dSLeon Romanovsky 	INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),
362a2a074efSLeon Romanovsky 	INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),
363e7610581SKamal Heib };
364e7610581SKamal Heib 
365e3cf00d0SUpinder Malhi /* Start of PF discovery section */
366e3cf00d0SUpinder Malhi static void *usnic_ib_device_add(struct pci_dev *dev)
367e3cf00d0SUpinder Malhi {
368e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
369e3cf00d0SUpinder Malhi 	union ib_gid gid;
3705d50f400SLeon Romanovsky 	struct in_device *ind;
371c7845bcaSUpinder Malhi 	struct net_device *netdev;
3725bb3c1e9SParvi Kaustubhi 	int ret;
373e3cf00d0SUpinder Malhi 
374e3cf00d0SUpinder Malhi 	usnic_dbg("\n");
375c7845bcaSUpinder Malhi 	netdev = pci_get_drvdata(dev);
376e3cf00d0SUpinder Malhi 
377459cc69fSLeon Romanovsky 	us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev);
3782c79dad8SInsu Yun 	if (!us_ibdev) {
379e3cf00d0SUpinder Malhi 		usnic_err("Device %s context alloc failed\n",
380e3cf00d0SUpinder Malhi 				netdev_name(pci_get_drvdata(dev)));
3812c79dad8SInsu Yun 		return ERR_PTR(-EFAULT);
382e3cf00d0SUpinder Malhi 	}
383e3cf00d0SUpinder Malhi 
384e3cf00d0SUpinder Malhi 	us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);
3852c79dad8SInsu Yun 	if (!us_ibdev->ufdev) {
3862c79dad8SInsu Yun 		usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev));
387e3cf00d0SUpinder Malhi 		goto err_dealloc;
388e3cf00d0SUpinder Malhi 	}
389e3cf00d0SUpinder Malhi 
390e3cf00d0SUpinder Malhi 	mutex_init(&us_ibdev->usdev_lock);
391e3cf00d0SUpinder Malhi 	INIT_LIST_HEAD(&us_ibdev->vf_dev_list);
392e3cf00d0SUpinder Malhi 	INIT_LIST_HEAD(&us_ibdev->ctx_list);
393e3cf00d0SUpinder Malhi 
394e3cf00d0SUpinder Malhi 	us_ibdev->pdev = dev;
395e3cf00d0SUpinder Malhi 	us_ibdev->netdev = pci_get_drvdata(dev);
39661f78268SUpinder Malhi 	us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP;
397e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT;
398e3cf00d0SUpinder Malhi 	us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS;
3996b06d52dSBart Van Assche 	us_ibdev->ib_dev.dev.parent = &dev->dev;
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 
422508a523fSParav Pandit 	rdma_set_device_sysfs_group(&us_ibdev->ib_dev, &usnic_attr_group);
423508a523fSParav Pandit 
4245bb3c1e9SParvi Kaustubhi 	ret = ib_device_set_netdev(&us_ibdev->ib_dev, us_ibdev->netdev, 1);
4255bb3c1e9SParvi Kaustubhi 	if (ret)
4265bb3c1e9SParvi Kaustubhi 		goto err_fwd_dealloc;
4275bb3c1e9SParvi Kaustubhi 
428*e0477b34SJason Gunthorpe 	dma_set_max_seg_size(&dev->dev, SZ_2G);
429*e0477b34SJason Gunthorpe 	if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d", &dev->dev))
430e3cf00d0SUpinder Malhi 		goto err_fwd_dealloc;
431e3cf00d0SUpinder Malhi 
4328af94ac6SUpinder Malhi 	usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu);
4338af94ac6SUpinder Malhi 	usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr);
4348af94ac6SUpinder Malhi 	if (netif_carrier_ok(us_ibdev->netdev))
4358af94ac6SUpinder Malhi 		usnic_fwd_carrier_up(us_ibdev->ufdev);
4368af94ac6SUpinder Malhi 
4372638eb8bSFlorian Westphal 	rcu_read_lock();
4382638eb8bSFlorian Westphal 	ind = __in_dev_get_rcu(netdev);
4392638eb8bSFlorian Westphal 	if (ind) {
4402638eb8bSFlorian Westphal 		const struct in_ifaddr *ifa;
4412638eb8bSFlorian Westphal 
4422638eb8bSFlorian Westphal 		ifa = rcu_dereference(ind->ifa_list);
4432638eb8bSFlorian Westphal 		if (ifa)
4442638eb8bSFlorian Westphal 			usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
4452638eb8bSFlorian Westphal 	}
4462638eb8bSFlorian Westphal 	rcu_read_unlock();
447c7845bcaSUpinder Malhi 
448c7845bcaSUpinder Malhi 	usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,
449c7845bcaSUpinder Malhi 				us_ibdev->ufdev->inaddr, &gid.raw[0]);
450e3cf00d0SUpinder Malhi 	memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,
451e3cf00d0SUpinder Malhi 		sizeof(gid.global.interface_id));
452e3cf00d0SUpinder Malhi 	kref_init(&us_ibdev->vf_cnt);
453e3cf00d0SUpinder Malhi 
454e3cf00d0SUpinder Malhi 	usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n",
4559de69861SJason Gunthorpe 		   dev_name(&us_ibdev->ib_dev.dev),
4569de69861SJason Gunthorpe 		   netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac,
4579de69861SJason Gunthorpe 		   us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu);
458e3cf00d0SUpinder Malhi 	return us_ibdev;
459e3cf00d0SUpinder Malhi 
460e3cf00d0SUpinder Malhi err_fwd_dealloc:
461e3cf00d0SUpinder Malhi 	usnic_fwd_dev_free(us_ibdev->ufdev);
462e3cf00d0SUpinder Malhi err_dealloc:
463e3cf00d0SUpinder Malhi 	usnic_err("failed -- deallocing device\n");
464e3cf00d0SUpinder Malhi 	ib_dealloc_device(&us_ibdev->ib_dev);
465e3cf00d0SUpinder Malhi 	return NULL;
466e3cf00d0SUpinder Malhi }
467e3cf00d0SUpinder Malhi 
468e3cf00d0SUpinder Malhi static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev)
469e3cf00d0SUpinder Malhi {
4709de69861SJason Gunthorpe 	usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev));
471e3cf00d0SUpinder Malhi 	usnic_ib_sysfs_unregister_usdev(us_ibdev);
472e3cf00d0SUpinder Malhi 	usnic_fwd_dev_free(us_ibdev->ufdev);
473e3cf00d0SUpinder Malhi 	ib_unregister_device(&us_ibdev->ib_dev);
474e3cf00d0SUpinder Malhi 	ib_dealloc_device(&us_ibdev->ib_dev);
475e3cf00d0SUpinder Malhi }
476e3cf00d0SUpinder Malhi 
477e3cf00d0SUpinder Malhi static void usnic_ib_undiscover_pf(struct kref *kref)
478e3cf00d0SUpinder Malhi {
479e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev, *tmp;
480e3cf00d0SUpinder Malhi 	struct pci_dev *dev;
481e3cf00d0SUpinder Malhi 	bool found = false;
482e3cf00d0SUpinder Malhi 
483e3cf00d0SUpinder Malhi 	dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev;
484e3cf00d0SUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
485e3cf00d0SUpinder Malhi 	list_for_each_entry_safe(us_ibdev, tmp,
486e3cf00d0SUpinder Malhi 				&usnic_ib_ibdev_list, ib_dev_link) {
487e3cf00d0SUpinder Malhi 		if (us_ibdev->pdev == dev) {
488e3cf00d0SUpinder Malhi 			list_del(&us_ibdev->ib_dev_link);
489e3cf00d0SUpinder Malhi 			found = true;
490e3cf00d0SUpinder Malhi 			break;
491e3cf00d0SUpinder Malhi 		}
492e3cf00d0SUpinder Malhi 	}
493e3cf00d0SUpinder Malhi 
494e3cf00d0SUpinder Malhi 
495e3cf00d0SUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
4960c236606SParvi Kaustubhi 	if (found)
4970c236606SParvi Kaustubhi 		usnic_ib_device_remove(us_ibdev);
4980c236606SParvi Kaustubhi 	else
4990c236606SParvi Kaustubhi 		WARN(1, "Failed to remove PF %s\n", pci_name(dev));
500e3cf00d0SUpinder Malhi }
501e3cf00d0SUpinder Malhi 
502e3cf00d0SUpinder Malhi static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic)
503e3cf00d0SUpinder Malhi {
504e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *us_ibdev;
505e3cf00d0SUpinder Malhi 	struct pci_dev *parent_pci, *vf_pci;
506e3cf00d0SUpinder Malhi 	int err;
507e3cf00d0SUpinder Malhi 
508e3cf00d0SUpinder Malhi 	vf_pci = usnic_vnic_get_pdev(vnic);
509e3cf00d0SUpinder Malhi 	parent_pci = pci_physfn(vf_pci);
510e3cf00d0SUpinder Malhi 
511e3cf00d0SUpinder Malhi 	BUG_ON(!parent_pci);
512e3cf00d0SUpinder Malhi 
513e3cf00d0SUpinder Malhi 	mutex_lock(&usnic_ib_ibdev_list_lock);
514e3cf00d0SUpinder Malhi 	list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
515e3cf00d0SUpinder Malhi 		if (us_ibdev->pdev == parent_pci) {
516e3cf00d0SUpinder Malhi 			kref_get(&us_ibdev->vf_cnt);
517e3cf00d0SUpinder Malhi 			goto out;
518e3cf00d0SUpinder Malhi 		}
519e3cf00d0SUpinder Malhi 	}
520e3cf00d0SUpinder Malhi 
521e3cf00d0SUpinder Malhi 	us_ibdev = usnic_ib_device_add(parent_pci);
522e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(us_ibdev)) {
5236a54d9f9SUpinder Malhi 		us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT);
524e3cf00d0SUpinder Malhi 		goto out;
525e3cf00d0SUpinder Malhi 	}
526e3cf00d0SUpinder Malhi 
527e3cf00d0SUpinder Malhi 	err = usnic_ib_sysfs_register_usdev(us_ibdev);
528e3cf00d0SUpinder Malhi 	if (err) {
529e3cf00d0SUpinder Malhi 		usnic_ib_device_remove(us_ibdev);
530e3cf00d0SUpinder Malhi 		us_ibdev = ERR_PTR(err);
531e3cf00d0SUpinder Malhi 		goto out;
532e3cf00d0SUpinder Malhi 	}
533e3cf00d0SUpinder Malhi 
534e3cf00d0SUpinder Malhi 	list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list);
535e3cf00d0SUpinder Malhi out:
536e3cf00d0SUpinder Malhi 	mutex_unlock(&usnic_ib_ibdev_list_lock);
537e3cf00d0SUpinder Malhi 	return us_ibdev;
538e3cf00d0SUpinder Malhi }
539e3cf00d0SUpinder Malhi /* End of PF discovery section */
540e3cf00d0SUpinder Malhi 
541e3cf00d0SUpinder Malhi /* Start of PCI section */
542e3cf00d0SUpinder Malhi 
5439baa3c34SBenoit Taine static const struct pci_device_id usnic_ib_pci_ids[] = {
544e3cf00d0SUpinder Malhi 	{PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
545e3cf00d0SUpinder Malhi 	{0,}
546e3cf00d0SUpinder Malhi };
547e3cf00d0SUpinder Malhi 
548e3cf00d0SUpinder Malhi static int usnic_ib_pci_probe(struct pci_dev *pdev,
549e3cf00d0SUpinder Malhi 				const struct pci_device_id *id)
550e3cf00d0SUpinder Malhi {
551e3cf00d0SUpinder Malhi 	int err;
552e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *pf;
553e3cf00d0SUpinder Malhi 	struct usnic_ib_vf *vf;
554e3cf00d0SUpinder Malhi 	enum usnic_vnic_res_type res_type;
555e3cf00d0SUpinder Malhi 
556e3cf00d0SUpinder Malhi 	vf = kzalloc(sizeof(*vf), GFP_KERNEL);
557e3cf00d0SUpinder Malhi 	if (!vf)
558e3cf00d0SUpinder Malhi 		return -ENOMEM;
559e3cf00d0SUpinder Malhi 
560e3cf00d0SUpinder Malhi 	err = pci_enable_device(pdev);
561e3cf00d0SUpinder Malhi 	if (err) {
562e3cf00d0SUpinder Malhi 		usnic_err("Failed to enable %s with err %d\n",
563e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
564e3cf00d0SUpinder Malhi 		goto out_clean_vf;
565e3cf00d0SUpinder Malhi 	}
566e3cf00d0SUpinder Malhi 
567e3cf00d0SUpinder Malhi 	err = pci_request_regions(pdev, DRV_NAME);
568e3cf00d0SUpinder Malhi 	if (err) {
569e3cf00d0SUpinder Malhi 		usnic_err("Failed to request region for %s with err %d\n",
570e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
571e3cf00d0SUpinder Malhi 		goto out_disable_device;
572e3cf00d0SUpinder Malhi 	}
573e3cf00d0SUpinder Malhi 
574e3cf00d0SUpinder Malhi 	pci_set_master(pdev);
575e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, vf);
576e3cf00d0SUpinder Malhi 
577e3cf00d0SUpinder Malhi 	vf->vnic = usnic_vnic_alloc(pdev);
578e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(vf->vnic)) {
5796a54d9f9SUpinder Malhi 		err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM;
580e3cf00d0SUpinder Malhi 		usnic_err("Failed to alloc vnic for %s with err %d\n",
581e3cf00d0SUpinder Malhi 				pci_name(pdev), err);
582e3cf00d0SUpinder Malhi 		goto out_release_regions;
583e3cf00d0SUpinder Malhi 	}
584e3cf00d0SUpinder Malhi 
585e3cf00d0SUpinder Malhi 	pf = usnic_ib_discover_pf(vf->vnic);
586e3cf00d0SUpinder Malhi 	if (IS_ERR_OR_NULL(pf)) {
587e3cf00d0SUpinder Malhi 		usnic_err("Failed to discover pf of vnic %s with err%ld\n",
588e3cf00d0SUpinder Malhi 				pci_name(pdev), PTR_ERR(pf));
5896a54d9f9SUpinder Malhi 		err = pf ? PTR_ERR(pf) : -EFAULT;
590e3cf00d0SUpinder Malhi 		goto out_clean_vnic;
591e3cf00d0SUpinder Malhi 	}
592e3cf00d0SUpinder Malhi 
593e3cf00d0SUpinder Malhi 	vf->pf = pf;
594e3cf00d0SUpinder Malhi 	spin_lock_init(&vf->lock);
595e3cf00d0SUpinder Malhi 	mutex_lock(&pf->usdev_lock);
596e3cf00d0SUpinder Malhi 	list_add_tail(&vf->link, &pf->vf_dev_list);
597e3cf00d0SUpinder Malhi 	/*
598e3cf00d0SUpinder Malhi 	 * Save max settings (will be same for each VF, easier to re-write than
599e3cf00d0SUpinder Malhi 	 * to say "if (!set) { set_values(); set=1; }
600e3cf00d0SUpinder Malhi 	 */
601e3cf00d0SUpinder Malhi 	for (res_type = USNIC_VNIC_RES_TYPE_EOL+1;
602e3cf00d0SUpinder Malhi 			res_type < USNIC_VNIC_RES_TYPE_MAX;
603e3cf00d0SUpinder Malhi 			res_type++) {
604e3cf00d0SUpinder Malhi 		pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic,
605e3cf00d0SUpinder Malhi 								res_type);
606e3cf00d0SUpinder Malhi 	}
607e3cf00d0SUpinder Malhi 
608e3cf00d0SUpinder Malhi 	mutex_unlock(&pf->usdev_lock);
609e3cf00d0SUpinder Malhi 
610e3cf00d0SUpinder Malhi 	usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev),
6119de69861SJason Gunthorpe 		   dev_name(&pf->ib_dev.dev));
612e3cf00d0SUpinder Malhi 	usnic_ib_log_vf(vf);
613e3cf00d0SUpinder Malhi 	return 0;
614e3cf00d0SUpinder Malhi 
615e3cf00d0SUpinder Malhi out_clean_vnic:
616e3cf00d0SUpinder Malhi 	usnic_vnic_free(vf->vnic);
617e3cf00d0SUpinder Malhi out_release_regions:
618e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, NULL);
619e3cf00d0SUpinder Malhi 	pci_clear_master(pdev);
620e3cf00d0SUpinder Malhi 	pci_release_regions(pdev);
621e3cf00d0SUpinder Malhi out_disable_device:
622e3cf00d0SUpinder Malhi 	pci_disable_device(pdev);
623e3cf00d0SUpinder Malhi out_clean_vf:
624e3cf00d0SUpinder Malhi 	kfree(vf);
625e3cf00d0SUpinder Malhi 	return err;
626e3cf00d0SUpinder Malhi }
627e3cf00d0SUpinder Malhi 
628e3cf00d0SUpinder Malhi static void usnic_ib_pci_remove(struct pci_dev *pdev)
629e3cf00d0SUpinder Malhi {
630e3cf00d0SUpinder Malhi 	struct usnic_ib_vf *vf = pci_get_drvdata(pdev);
631e3cf00d0SUpinder Malhi 	struct usnic_ib_dev *pf = vf->pf;
632e3cf00d0SUpinder Malhi 
633e3cf00d0SUpinder Malhi 	mutex_lock(&pf->usdev_lock);
634e3cf00d0SUpinder Malhi 	list_del(&vf->link);
635e3cf00d0SUpinder Malhi 	mutex_unlock(&pf->usdev_lock);
636e3cf00d0SUpinder Malhi 
637e3cf00d0SUpinder Malhi 	kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf);
638e3cf00d0SUpinder Malhi 	usnic_vnic_free(vf->vnic);
639e3cf00d0SUpinder Malhi 	pci_set_drvdata(pdev, NULL);
640e3cf00d0SUpinder Malhi 	pci_clear_master(pdev);
641e3cf00d0SUpinder Malhi 	pci_release_regions(pdev);
642e3cf00d0SUpinder Malhi 	pci_disable_device(pdev);
643e3cf00d0SUpinder Malhi 	kfree(vf);
644e3cf00d0SUpinder Malhi 
645e3cf00d0SUpinder Malhi 	usnic_info("Removed VF %s\n", pci_name(pdev));
646e3cf00d0SUpinder Malhi }
647e3cf00d0SUpinder Malhi 
648e3cf00d0SUpinder Malhi /* PCI driver entry points */
649e3cf00d0SUpinder Malhi static struct pci_driver usnic_ib_pci_driver = {
650e3cf00d0SUpinder Malhi 	.name = DRV_NAME,
651e3cf00d0SUpinder Malhi 	.id_table = usnic_ib_pci_ids,
652e3cf00d0SUpinder Malhi 	.probe = usnic_ib_pci_probe,
653e3cf00d0SUpinder Malhi 	.remove = usnic_ib_pci_remove,
654e3cf00d0SUpinder Malhi };
655e3cf00d0SUpinder Malhi /* End of PCI section */
656e3cf00d0SUpinder Malhi 
657e3cf00d0SUpinder Malhi /* Start of module section */
658e3cf00d0SUpinder Malhi static int __init usnic_ib_init(void)
659e3cf00d0SUpinder Malhi {
660e3cf00d0SUpinder Malhi 	int err;
661e3cf00d0SUpinder Malhi 
662e3cf00d0SUpinder Malhi 	printk_once(KERN_INFO "%s", usnic_version);
663e3cf00d0SUpinder Malhi 
664e3cf00d0SUpinder Malhi 	err = usnic_uiom_init(DRV_NAME);
665e3cf00d0SUpinder Malhi 	if (err) {
666901018f2SColin Ian King 		usnic_err("Unable to initialize umem with err %d\n", err);
667e3cf00d0SUpinder Malhi 		return err;
668e3cf00d0SUpinder Malhi 	}
669e3cf00d0SUpinder Malhi 
67086cd747cSChristophe Jaillet 	err = pci_register_driver(&usnic_ib_pci_driver);
67186cd747cSChristophe Jaillet 	if (err) {
672e3cf00d0SUpinder Malhi 		usnic_err("Unable to register with PCI\n");
673e3cf00d0SUpinder Malhi 		goto out_umem_fini;
674e3cf00d0SUpinder Malhi 	}
675e3cf00d0SUpinder Malhi 
676e3cf00d0SUpinder Malhi 	err = register_netdevice_notifier(&usnic_ib_netdevice_notifier);
677e3cf00d0SUpinder Malhi 	if (err) {
678e3cf00d0SUpinder Malhi 		usnic_err("Failed to register netdev notifier\n");
679e3cf00d0SUpinder Malhi 		goto out_pci_unreg;
680e3cf00d0SUpinder Malhi 	}
681e3cf00d0SUpinder Malhi 
682c7845bcaSUpinder Malhi 	err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
683c7845bcaSUpinder Malhi 	if (err) {
684c7845bcaSUpinder Malhi 		usnic_err("Failed to register inet addr notifier\n");
685c7845bcaSUpinder Malhi 		goto out_unreg_netdev_notifier;
686c7845bcaSUpinder Malhi 	}
687c7845bcaSUpinder Malhi 
688e3cf00d0SUpinder Malhi 	err = usnic_transport_init();
689e3cf00d0SUpinder Malhi 	if (err) {
690e3cf00d0SUpinder Malhi 		usnic_err("Failed to initialize transport\n");
691c7845bcaSUpinder Malhi 		goto out_unreg_inetaddr_notifier;
692e3cf00d0SUpinder Malhi 	}
693e3cf00d0SUpinder Malhi 
694e3cf00d0SUpinder Malhi 	usnic_debugfs_init();
695e3cf00d0SUpinder Malhi 
696e3cf00d0SUpinder Malhi 	return 0;
697e3cf00d0SUpinder Malhi 
698c7845bcaSUpinder Malhi out_unreg_inetaddr_notifier:
699c7845bcaSUpinder Malhi 	unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
700e3cf00d0SUpinder Malhi out_unreg_netdev_notifier:
701e3cf00d0SUpinder Malhi 	unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
702e3cf00d0SUpinder Malhi out_pci_unreg:
703e3cf00d0SUpinder Malhi 	pci_unregister_driver(&usnic_ib_pci_driver);
704e3cf00d0SUpinder Malhi out_umem_fini:
705e3cf00d0SUpinder Malhi 
706e3cf00d0SUpinder Malhi 	return err;
707e3cf00d0SUpinder Malhi }
708e3cf00d0SUpinder Malhi 
709e3cf00d0SUpinder Malhi static void __exit usnic_ib_destroy(void)
710e3cf00d0SUpinder Malhi {
711e3cf00d0SUpinder Malhi 	usnic_dbg("\n");
712e3cf00d0SUpinder Malhi 	usnic_debugfs_exit();
713e3cf00d0SUpinder Malhi 	usnic_transport_fini();
714c7845bcaSUpinder Malhi 	unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
715e3cf00d0SUpinder Malhi 	unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
716e3cf00d0SUpinder Malhi 	pci_unregister_driver(&usnic_ib_pci_driver);
717e3cf00d0SUpinder Malhi }
718e3cf00d0SUpinder Malhi 
719e3cf00d0SUpinder Malhi MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver");
720e3cf00d0SUpinder Malhi MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>");
721e3cf00d0SUpinder Malhi MODULE_LICENSE("Dual BSD/GPL");
722e3cf00d0SUpinder Malhi module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR);
723e3cf00d0SUpinder Malhi module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR);
724e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3");
725e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs");
726e3cf00d0SUpinder Malhi MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids);
727e3cf00d0SUpinder Malhi 
728e3cf00d0SUpinder Malhi module_init(usnic_ib_init);
729e3cf00d0SUpinder Malhi module_exit(usnic_ib_destroy);
730e3cf00d0SUpinder Malhi /* End of module section */
731