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 */
usnic_ib_dump_vf_hdr(void * obj,char * buf,int buf_sz)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
usnic_ib_dump_vf(struct usnic_ib_vf * vf,char * buf,int buf_sz)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
usnic_ib_log_vf(struct usnic_ib_vf * vf)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 */
usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev * us_ibdev)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
usnic_ib_handle_usdev_event(struct usnic_ib_dev * us_ibdev,unsigned long event)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
usnic_ib_netdevice_event(struct notifier_block * notifier,unsigned long event,void * ptr)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 */
usnic_ib_handle_inet_event(struct usnic_ib_dev * us_ibdev,unsigned long event,void * ptr)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
usnic_ib_inetaddr_event(struct notifier_block * notifier,unsigned long event,void * ptr)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
usnic_port_immutable(struct ib_device * ibdev,u32 port_num,struct ib_port_immutable * immutable)3061fb7f897SMark Bloch static int usnic_port_immutable(struct ib_device *ibdev, u32 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
usnic_get_dev_fw_str(struct ib_device * device,char * str)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,
350915e4af5SJason Gunthorpe .device_group = &usnic_attr_group,
351e7610581SKamal Heib .get_dev_fw_str = usnic_get_dev_fw_str,
352e7610581SKamal Heib .get_link_layer = usnic_ib_port_link_layer,
353e7610581SKamal Heib .get_port_immutable = usnic_port_immutable,
354e7610581SKamal Heib .mmap = usnic_ib_mmap,
355e7610581SKamal Heib .modify_qp = usnic_ib_modify_qp,
356e7610581SKamal Heib .query_device = usnic_ib_query_device,
357e7610581SKamal Heib .query_gid = usnic_ib_query_gid,
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,
36121a428a0SLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),
362e39afe3dSLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),
363514aee66SLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_qp, usnic_ib_qp_grp, ibqp),
364a2a074efSLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),
365e7610581SKamal Heib };
366e7610581SKamal Heib
367e3cf00d0SUpinder Malhi /* Start of PF discovery section */
usnic_ib_device_add(struct pci_dev * dev)368e3cf00d0SUpinder Malhi static void *usnic_ib_device_add(struct pci_dev *dev)
369e3cf00d0SUpinder Malhi {
370e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev;
371e3cf00d0SUpinder Malhi union ib_gid gid;
3725d50f400SLeon Romanovsky struct in_device *ind;
373c7845bcaSUpinder Malhi struct net_device *netdev;
3745bb3c1e9SParvi Kaustubhi int ret;
375e3cf00d0SUpinder Malhi
376e3cf00d0SUpinder Malhi usnic_dbg("\n");
377c7845bcaSUpinder Malhi netdev = pci_get_drvdata(dev);
378e3cf00d0SUpinder Malhi
379459cc69fSLeon Romanovsky us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev);
3802c79dad8SInsu Yun if (!us_ibdev) {
381e3cf00d0SUpinder Malhi usnic_err("Device %s context alloc failed\n",
382e3cf00d0SUpinder Malhi netdev_name(pci_get_drvdata(dev)));
3832c79dad8SInsu Yun return ERR_PTR(-EFAULT);
384e3cf00d0SUpinder Malhi }
385e3cf00d0SUpinder Malhi
386e3cf00d0SUpinder Malhi us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);
3872c79dad8SInsu Yun if (!us_ibdev->ufdev) {
3882c79dad8SInsu Yun usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev));
389e3cf00d0SUpinder Malhi goto err_dealloc;
390e3cf00d0SUpinder Malhi }
391e3cf00d0SUpinder Malhi
392e3cf00d0SUpinder Malhi mutex_init(&us_ibdev->usdev_lock);
393e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->vf_dev_list);
394e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->ctx_list);
395e3cf00d0SUpinder Malhi
396e3cf00d0SUpinder Malhi us_ibdev->pdev = dev;
397e3cf00d0SUpinder Malhi us_ibdev->netdev = pci_get_drvdata(dev);
39861f78268SUpinder Malhi us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP;
399e3cf00d0SUpinder Malhi us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT;
400e3cf00d0SUpinder Malhi us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS;
4016b06d52dSBart Van Assche us_ibdev->ib_dev.dev.parent = &dev->dev;
402e3cf00d0SUpinder Malhi
403e7610581SKamal Heib ib_set_device_ops(&us_ibdev->ib_dev, &usnic_dev_ops);
404e3cf00d0SUpinder Malhi
4055bb3c1e9SParvi Kaustubhi ret = ib_device_set_netdev(&us_ibdev->ib_dev, us_ibdev->netdev, 1);
4065bb3c1e9SParvi Kaustubhi if (ret)
4075bb3c1e9SParvi Kaustubhi goto err_fwd_dealloc;
4085bb3c1e9SParvi Kaustubhi
409e0477b34SJason Gunthorpe dma_set_max_seg_size(&dev->dev, SZ_2G);
410e0477b34SJason Gunthorpe if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d", &dev->dev))
411e3cf00d0SUpinder Malhi goto err_fwd_dealloc;
412e3cf00d0SUpinder Malhi
4138af94ac6SUpinder Malhi usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu);
4148af94ac6SUpinder Malhi usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr);
4158af94ac6SUpinder Malhi if (netif_carrier_ok(us_ibdev->netdev))
4168af94ac6SUpinder Malhi usnic_fwd_carrier_up(us_ibdev->ufdev);
4178af94ac6SUpinder Malhi
4182638eb8bSFlorian Westphal rcu_read_lock();
4192638eb8bSFlorian Westphal ind = __in_dev_get_rcu(netdev);
4202638eb8bSFlorian Westphal if (ind) {
4212638eb8bSFlorian Westphal const struct in_ifaddr *ifa;
4222638eb8bSFlorian Westphal
4232638eb8bSFlorian Westphal ifa = rcu_dereference(ind->ifa_list);
4242638eb8bSFlorian Westphal if (ifa)
4252638eb8bSFlorian Westphal usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
4262638eb8bSFlorian Westphal }
4272638eb8bSFlorian Westphal rcu_read_unlock();
428c7845bcaSUpinder Malhi
429c7845bcaSUpinder Malhi usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,
430c7845bcaSUpinder Malhi us_ibdev->ufdev->inaddr, &gid.raw[0]);
431e3cf00d0SUpinder Malhi memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,
432e3cf00d0SUpinder Malhi sizeof(gid.global.interface_id));
433e3cf00d0SUpinder Malhi kref_init(&us_ibdev->vf_cnt);
434e3cf00d0SUpinder Malhi
435e3cf00d0SUpinder Malhi usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n",
4369de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev),
4379de69861SJason Gunthorpe netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac,
4389de69861SJason Gunthorpe us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu);
439e3cf00d0SUpinder Malhi return us_ibdev;
440e3cf00d0SUpinder Malhi
441e3cf00d0SUpinder Malhi err_fwd_dealloc:
442e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev);
443e3cf00d0SUpinder Malhi err_dealloc:
444e3cf00d0SUpinder Malhi usnic_err("failed -- deallocing device\n");
445e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev);
446e3cf00d0SUpinder Malhi return NULL;
447e3cf00d0SUpinder Malhi }
448e3cf00d0SUpinder Malhi
usnic_ib_device_remove(struct usnic_ib_dev * us_ibdev)449e3cf00d0SUpinder Malhi static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev)
450e3cf00d0SUpinder Malhi {
4519de69861SJason Gunthorpe usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev));
452e3cf00d0SUpinder Malhi usnic_ib_sysfs_unregister_usdev(us_ibdev);
453e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev);
454e3cf00d0SUpinder Malhi ib_unregister_device(&us_ibdev->ib_dev);
455e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev);
456e3cf00d0SUpinder Malhi }
457e3cf00d0SUpinder Malhi
usnic_ib_undiscover_pf(struct kref * kref)458e3cf00d0SUpinder Malhi static void usnic_ib_undiscover_pf(struct kref *kref)
459e3cf00d0SUpinder Malhi {
460e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev, *tmp;
461e3cf00d0SUpinder Malhi struct pci_dev *dev;
462e3cf00d0SUpinder Malhi bool found = false;
463e3cf00d0SUpinder Malhi
464e3cf00d0SUpinder Malhi dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev;
465e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock);
466e3cf00d0SUpinder Malhi list_for_each_entry_safe(us_ibdev, tmp,
467e3cf00d0SUpinder Malhi &usnic_ib_ibdev_list, ib_dev_link) {
468e3cf00d0SUpinder Malhi if (us_ibdev->pdev == dev) {
469e3cf00d0SUpinder Malhi list_del(&us_ibdev->ib_dev_link);
470e3cf00d0SUpinder Malhi found = true;
471e3cf00d0SUpinder Malhi break;
472e3cf00d0SUpinder Malhi }
473e3cf00d0SUpinder Malhi }
474e3cf00d0SUpinder Malhi
475e3cf00d0SUpinder Malhi
476e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock);
4770c236606SParvi Kaustubhi if (found)
4780c236606SParvi Kaustubhi usnic_ib_device_remove(us_ibdev);
4790c236606SParvi Kaustubhi else
4800c236606SParvi Kaustubhi WARN(1, "Failed to remove PF %s\n", pci_name(dev));
481e3cf00d0SUpinder Malhi }
482e3cf00d0SUpinder Malhi
usnic_ib_discover_pf(struct usnic_vnic * vnic)483e3cf00d0SUpinder Malhi static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic)
484e3cf00d0SUpinder Malhi {
485e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev;
486e3cf00d0SUpinder Malhi struct pci_dev *parent_pci, *vf_pci;
487e3cf00d0SUpinder Malhi int err;
488e3cf00d0SUpinder Malhi
489e3cf00d0SUpinder Malhi vf_pci = usnic_vnic_get_pdev(vnic);
490e3cf00d0SUpinder Malhi parent_pci = pci_physfn(vf_pci);
491e3cf00d0SUpinder Malhi
492e3cf00d0SUpinder Malhi BUG_ON(!parent_pci);
493e3cf00d0SUpinder Malhi
494e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock);
495e3cf00d0SUpinder Malhi list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
496e3cf00d0SUpinder Malhi if (us_ibdev->pdev == parent_pci) {
497e3cf00d0SUpinder Malhi kref_get(&us_ibdev->vf_cnt);
498e3cf00d0SUpinder Malhi goto out;
499e3cf00d0SUpinder Malhi }
500e3cf00d0SUpinder Malhi }
501e3cf00d0SUpinder Malhi
502e3cf00d0SUpinder Malhi us_ibdev = usnic_ib_device_add(parent_pci);
503e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(us_ibdev)) {
5046a54d9f9SUpinder Malhi us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT);
505e3cf00d0SUpinder Malhi goto out;
506e3cf00d0SUpinder Malhi }
507e3cf00d0SUpinder Malhi
508e3cf00d0SUpinder Malhi err = usnic_ib_sysfs_register_usdev(us_ibdev);
509e3cf00d0SUpinder Malhi if (err) {
510e3cf00d0SUpinder Malhi usnic_ib_device_remove(us_ibdev);
511e3cf00d0SUpinder Malhi us_ibdev = ERR_PTR(err);
512e3cf00d0SUpinder Malhi goto out;
513e3cf00d0SUpinder Malhi }
514e3cf00d0SUpinder Malhi
515e3cf00d0SUpinder Malhi list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list);
516e3cf00d0SUpinder Malhi out:
517e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock);
518e3cf00d0SUpinder Malhi return us_ibdev;
519e3cf00d0SUpinder Malhi }
520e3cf00d0SUpinder Malhi /* End of PF discovery section */
521e3cf00d0SUpinder Malhi
522e3cf00d0SUpinder Malhi /* Start of PCI section */
523e3cf00d0SUpinder Malhi
5249baa3c34SBenoit Taine static const struct pci_device_id usnic_ib_pci_ids[] = {
525e3cf00d0SUpinder Malhi {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
526e3cf00d0SUpinder Malhi {0,}
527e3cf00d0SUpinder Malhi };
528e3cf00d0SUpinder Malhi
usnic_ib_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)529e3cf00d0SUpinder Malhi static int usnic_ib_pci_probe(struct pci_dev *pdev,
530e3cf00d0SUpinder Malhi const struct pci_device_id *id)
531e3cf00d0SUpinder Malhi {
532e3cf00d0SUpinder Malhi int err;
533e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf;
534e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf;
535e3cf00d0SUpinder Malhi enum usnic_vnic_res_type res_type;
536e3cf00d0SUpinder Malhi
537*d9539fb7SRobin Murphy if (!device_iommu_mapped(&pdev->dev)) {
538*d9539fb7SRobin Murphy usnic_err("IOMMU required but not present or enabled. USNIC QPs will not function w/o enabling IOMMU\n");
539*d9539fb7SRobin Murphy return -EPERM;
540*d9539fb7SRobin Murphy }
541*d9539fb7SRobin Murphy
542e3cf00d0SUpinder Malhi vf = kzalloc(sizeof(*vf), GFP_KERNEL);
543e3cf00d0SUpinder Malhi if (!vf)
544e3cf00d0SUpinder Malhi return -ENOMEM;
545e3cf00d0SUpinder Malhi
546e3cf00d0SUpinder Malhi err = pci_enable_device(pdev);
547e3cf00d0SUpinder Malhi if (err) {
548e3cf00d0SUpinder Malhi usnic_err("Failed to enable %s with err %d\n",
549e3cf00d0SUpinder Malhi pci_name(pdev), err);
550e3cf00d0SUpinder Malhi goto out_clean_vf;
551e3cf00d0SUpinder Malhi }
552e3cf00d0SUpinder Malhi
553e3cf00d0SUpinder Malhi err = pci_request_regions(pdev, DRV_NAME);
554e3cf00d0SUpinder Malhi if (err) {
555e3cf00d0SUpinder Malhi usnic_err("Failed to request region for %s with err %d\n",
556e3cf00d0SUpinder Malhi pci_name(pdev), err);
557e3cf00d0SUpinder Malhi goto out_disable_device;
558e3cf00d0SUpinder Malhi }
559e3cf00d0SUpinder Malhi
560e3cf00d0SUpinder Malhi pci_set_master(pdev);
561e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, vf);
562e3cf00d0SUpinder Malhi
563e3cf00d0SUpinder Malhi vf->vnic = usnic_vnic_alloc(pdev);
564e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(vf->vnic)) {
5656a54d9f9SUpinder Malhi err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM;
566e3cf00d0SUpinder Malhi usnic_err("Failed to alloc vnic for %s with err %d\n",
567e3cf00d0SUpinder Malhi pci_name(pdev), err);
568e3cf00d0SUpinder Malhi goto out_release_regions;
569e3cf00d0SUpinder Malhi }
570e3cf00d0SUpinder Malhi
571e3cf00d0SUpinder Malhi pf = usnic_ib_discover_pf(vf->vnic);
572e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(pf)) {
573e3cf00d0SUpinder Malhi usnic_err("Failed to discover pf of vnic %s with err%ld\n",
574e3cf00d0SUpinder Malhi pci_name(pdev), PTR_ERR(pf));
5756a54d9f9SUpinder Malhi err = pf ? PTR_ERR(pf) : -EFAULT;
576e3cf00d0SUpinder Malhi goto out_clean_vnic;
577e3cf00d0SUpinder Malhi }
578e3cf00d0SUpinder Malhi
579e3cf00d0SUpinder Malhi vf->pf = pf;
580a86cd017SLeon Romanovsky mutex_init(&vf->lock);
581e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock);
582e3cf00d0SUpinder Malhi list_add_tail(&vf->link, &pf->vf_dev_list);
583e3cf00d0SUpinder Malhi /*
584e3cf00d0SUpinder Malhi * Save max settings (will be same for each VF, easier to re-write than
585e3cf00d0SUpinder Malhi * to say "if (!set) { set_values(); set=1; }
586e3cf00d0SUpinder Malhi */
587e3cf00d0SUpinder Malhi for (res_type = USNIC_VNIC_RES_TYPE_EOL+1;
588e3cf00d0SUpinder Malhi res_type < USNIC_VNIC_RES_TYPE_MAX;
589e3cf00d0SUpinder Malhi res_type++) {
590e3cf00d0SUpinder Malhi pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic,
591e3cf00d0SUpinder Malhi res_type);
592e3cf00d0SUpinder Malhi }
593e3cf00d0SUpinder Malhi
594e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock);
595e3cf00d0SUpinder Malhi
596e3cf00d0SUpinder Malhi usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev),
5979de69861SJason Gunthorpe dev_name(&pf->ib_dev.dev));
598e3cf00d0SUpinder Malhi usnic_ib_log_vf(vf);
599e3cf00d0SUpinder Malhi return 0;
600e3cf00d0SUpinder Malhi
601e3cf00d0SUpinder Malhi out_clean_vnic:
602e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic);
603e3cf00d0SUpinder Malhi out_release_regions:
604e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL);
605e3cf00d0SUpinder Malhi pci_release_regions(pdev);
606e3cf00d0SUpinder Malhi out_disable_device:
607e3cf00d0SUpinder Malhi pci_disable_device(pdev);
608e3cf00d0SUpinder Malhi out_clean_vf:
609e3cf00d0SUpinder Malhi kfree(vf);
610e3cf00d0SUpinder Malhi return err;
611e3cf00d0SUpinder Malhi }
612e3cf00d0SUpinder Malhi
usnic_ib_pci_remove(struct pci_dev * pdev)613e3cf00d0SUpinder Malhi static void usnic_ib_pci_remove(struct pci_dev *pdev)
614e3cf00d0SUpinder Malhi {
615e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf = pci_get_drvdata(pdev);
616e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf = vf->pf;
617e3cf00d0SUpinder Malhi
618e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock);
619e3cf00d0SUpinder Malhi list_del(&vf->link);
620e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock);
621e3cf00d0SUpinder Malhi
622e3cf00d0SUpinder Malhi kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf);
623e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic);
624e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL);
625e3cf00d0SUpinder Malhi pci_release_regions(pdev);
626e3cf00d0SUpinder Malhi pci_disable_device(pdev);
627e3cf00d0SUpinder Malhi kfree(vf);
628e3cf00d0SUpinder Malhi
629e3cf00d0SUpinder Malhi usnic_info("Removed VF %s\n", pci_name(pdev));
630e3cf00d0SUpinder Malhi }
631e3cf00d0SUpinder Malhi
632e3cf00d0SUpinder Malhi /* PCI driver entry points */
633e3cf00d0SUpinder Malhi static struct pci_driver usnic_ib_pci_driver = {
634e3cf00d0SUpinder Malhi .name = DRV_NAME,
635e3cf00d0SUpinder Malhi .id_table = usnic_ib_pci_ids,
636e3cf00d0SUpinder Malhi .probe = usnic_ib_pci_probe,
637e3cf00d0SUpinder Malhi .remove = usnic_ib_pci_remove,
638e3cf00d0SUpinder Malhi };
639e3cf00d0SUpinder Malhi /* End of PCI section */
640e3cf00d0SUpinder Malhi
641e3cf00d0SUpinder Malhi /* Start of module section */
usnic_ib_init(void)642e3cf00d0SUpinder Malhi static int __init usnic_ib_init(void)
643e3cf00d0SUpinder Malhi {
644e3cf00d0SUpinder Malhi int err;
645e3cf00d0SUpinder Malhi
646e3cf00d0SUpinder Malhi printk_once(KERN_INFO "%s", usnic_version);
647e3cf00d0SUpinder Malhi
64886cd747cSChristophe Jaillet err = pci_register_driver(&usnic_ib_pci_driver);
64986cd747cSChristophe Jaillet if (err) {
650e3cf00d0SUpinder Malhi usnic_err("Unable to register with PCI\n");
651e3cf00d0SUpinder Malhi goto out_umem_fini;
652e3cf00d0SUpinder Malhi }
653e3cf00d0SUpinder Malhi
654e3cf00d0SUpinder Malhi err = register_netdevice_notifier(&usnic_ib_netdevice_notifier);
655e3cf00d0SUpinder Malhi if (err) {
656e3cf00d0SUpinder Malhi usnic_err("Failed to register netdev notifier\n");
657e3cf00d0SUpinder Malhi goto out_pci_unreg;
658e3cf00d0SUpinder Malhi }
659e3cf00d0SUpinder Malhi
660c7845bcaSUpinder Malhi err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
661c7845bcaSUpinder Malhi if (err) {
662c7845bcaSUpinder Malhi usnic_err("Failed to register inet addr notifier\n");
663c7845bcaSUpinder Malhi goto out_unreg_netdev_notifier;
664c7845bcaSUpinder Malhi }
665c7845bcaSUpinder Malhi
666e3cf00d0SUpinder Malhi err = usnic_transport_init();
667e3cf00d0SUpinder Malhi if (err) {
668e3cf00d0SUpinder Malhi usnic_err("Failed to initialize transport\n");
669c7845bcaSUpinder Malhi goto out_unreg_inetaddr_notifier;
670e3cf00d0SUpinder Malhi }
671e3cf00d0SUpinder Malhi
672e3cf00d0SUpinder Malhi usnic_debugfs_init();
673e3cf00d0SUpinder Malhi
674e3cf00d0SUpinder Malhi return 0;
675e3cf00d0SUpinder Malhi
676c7845bcaSUpinder Malhi out_unreg_inetaddr_notifier:
677c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
678e3cf00d0SUpinder Malhi out_unreg_netdev_notifier:
679e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
680e3cf00d0SUpinder Malhi out_pci_unreg:
681e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver);
682e3cf00d0SUpinder Malhi out_umem_fini:
683e3cf00d0SUpinder Malhi
684e3cf00d0SUpinder Malhi return err;
685e3cf00d0SUpinder Malhi }
686e3cf00d0SUpinder Malhi
usnic_ib_destroy(void)687e3cf00d0SUpinder Malhi static void __exit usnic_ib_destroy(void)
688e3cf00d0SUpinder Malhi {
689e3cf00d0SUpinder Malhi usnic_dbg("\n");
690e3cf00d0SUpinder Malhi usnic_debugfs_exit();
691e3cf00d0SUpinder Malhi usnic_transport_fini();
692c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
693e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
694e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver);
695e3cf00d0SUpinder Malhi }
696e3cf00d0SUpinder Malhi
697e3cf00d0SUpinder Malhi MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver");
698e3cf00d0SUpinder Malhi MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>");
699e3cf00d0SUpinder Malhi MODULE_LICENSE("Dual BSD/GPL");
700e3cf00d0SUpinder Malhi module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR);
701e3cf00d0SUpinder Malhi module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR);
702e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3");
703e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs");
704e3cf00d0SUpinder Malhi MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids);
705e3cf00d0SUpinder Malhi
706e3cf00d0SUpinder Malhi module_init(usnic_ib_init);
707e3cf00d0SUpinder Malhi module_exit(usnic_ib_destroy);
708e3cf00d0SUpinder Malhi /* End of module section */
709