xref: /freebsd-src/sys/dev/irdma/icrdma.c (revision 5b5f7d0e77a9eee73eb5d596f43aef4e1a3674d8)
1cdcd52d4SBartosz Sobczak /*-
2cdcd52d4SBartosz Sobczak  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3cdcd52d4SBartosz Sobczak  *
401fbb869SBartosz Sobczak  * Copyright (c) 2021 - 2023 Intel Corporation
5cdcd52d4SBartosz Sobczak  *
6cdcd52d4SBartosz Sobczak  * This software is available to you under a choice of one of two
7cdcd52d4SBartosz Sobczak  * licenses.  You may choose to be licensed under the terms of the GNU
8cdcd52d4SBartosz Sobczak  * General Public License (GPL) Version 2, available from the file
9cdcd52d4SBartosz Sobczak  * COPYING in the main directory of this source tree, or the
10cdcd52d4SBartosz Sobczak  * OpenFabrics.org BSD license below:
11cdcd52d4SBartosz Sobczak  *
12cdcd52d4SBartosz Sobczak  *   Redistribution and use in source and binary forms, with or
13cdcd52d4SBartosz Sobczak  *   without modification, are permitted provided that the following
14cdcd52d4SBartosz Sobczak  *   conditions are met:
15cdcd52d4SBartosz Sobczak  *
16cdcd52d4SBartosz Sobczak  *    - Redistributions of source code must retain the above
17cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
18cdcd52d4SBartosz Sobczak  *	disclaimer.
19cdcd52d4SBartosz Sobczak  *
20cdcd52d4SBartosz Sobczak  *    - Redistributions in binary form must reproduce the above
21cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
22cdcd52d4SBartosz Sobczak  *	disclaimer in the documentation and/or other materials
23cdcd52d4SBartosz Sobczak  *	provided with the distribution.
24cdcd52d4SBartosz Sobczak  *
25cdcd52d4SBartosz Sobczak  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26cdcd52d4SBartosz Sobczak  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27cdcd52d4SBartosz Sobczak  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28cdcd52d4SBartosz Sobczak  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29cdcd52d4SBartosz Sobczak  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30cdcd52d4SBartosz Sobczak  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31cdcd52d4SBartosz Sobczak  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32cdcd52d4SBartosz Sobczak  * SOFTWARE.
33cdcd52d4SBartosz Sobczak  */
34cdcd52d4SBartosz Sobczak 
35cdcd52d4SBartosz Sobczak #include <sys/param.h>
36cdcd52d4SBartosz Sobczak #include <sys/systm.h>
37cdcd52d4SBartosz Sobczak #include <sys/bus.h>
38cdcd52d4SBartosz Sobczak #include <sys/kernel.h>
39cdcd52d4SBartosz Sobczak #include <sys/module.h>
40cdcd52d4SBartosz Sobczak #include <sys/sysctl.h>
41cdcd52d4SBartosz Sobczak #include <machine/bus.h>
42cdcd52d4SBartosz Sobczak #include <linux/device.h>
43cdcd52d4SBartosz Sobczak #include <sys/rman.h>
44cdcd52d4SBartosz Sobczak 
45cdcd52d4SBartosz Sobczak #include "ice_rdma.h"
46cdcd52d4SBartosz Sobczak #include "irdma_main.h"
47cdcd52d4SBartosz Sobczak #include "icrdma_hw.h"
48cdcd52d4SBartosz Sobczak 
49cdcd52d4SBartosz Sobczak #include "irdma_if.h"
50cdcd52d4SBartosz Sobczak #include "irdma_di_if.h"
51cdcd52d4SBartosz Sobczak 
52cdcd52d4SBartosz Sobczak /**
53cdcd52d4SBartosz Sobczak  *  Driver version
54cdcd52d4SBartosz Sobczak  */
55*5b5f7d0eSBartosz Sobczak char irdma_driver_version[] = "1.2.36-k";
56cdcd52d4SBartosz Sobczak 
57cdcd52d4SBartosz Sobczak /**
58cdcd52d4SBartosz Sobczak  * irdma_init_tunable - prepare tunables
59cdcd52d4SBartosz Sobczak  * @rf: RDMA PCI function
60cdcd52d4SBartosz Sobczak  * @pf_id: id of the pf
61cdcd52d4SBartosz Sobczak  */
62cdcd52d4SBartosz Sobczak static void
irdma_init_tunable(struct irdma_pci_f * rf,uint8_t pf_id)63cdcd52d4SBartosz Sobczak irdma_init_tunable(struct irdma_pci_f *rf, uint8_t pf_id)
64cdcd52d4SBartosz Sobczak {
6501fbb869SBartosz Sobczak 	struct sysctl_oid_list *irdma_oid_list;
6601fbb869SBartosz Sobczak 	struct irdma_tunable_info *t_info = &rf->tun_info;
67cdcd52d4SBartosz Sobczak 	char pf_name[16];
68cdcd52d4SBartosz Sobczak 
69cdcd52d4SBartosz Sobczak 	snprintf(pf_name, 15, "irdma%d", pf_id);
7001fbb869SBartosz Sobczak 	sysctl_ctx_init(&t_info->irdma_sysctl_ctx);
71cdcd52d4SBartosz Sobczak 
7201fbb869SBartosz Sobczak 	t_info->irdma_sysctl_tree = SYSCTL_ADD_NODE(&t_info->irdma_sysctl_ctx,
73cdcd52d4SBartosz Sobczak 						    SYSCTL_STATIC_CHILDREN(_dev),
7401fbb869SBartosz Sobczak 						    OID_AUTO, pf_name,
7501fbb869SBartosz Sobczak 						    CTLFLAG_RD, NULL, "");
7601fbb869SBartosz Sobczak 
7701fbb869SBartosz Sobczak 	irdma_oid_list = SYSCTL_CHILDREN(t_info->irdma_sysctl_tree);
7801fbb869SBartosz Sobczak 
7901fbb869SBartosz Sobczak 	t_info->sws_sysctl_tree = SYSCTL_ADD_NODE(&t_info->irdma_sysctl_ctx,
8001fbb869SBartosz Sobczak 						  irdma_oid_list, OID_AUTO,
8101fbb869SBartosz Sobczak 						  "sw_stats", CTLFLAG_RD,
82cdcd52d4SBartosz Sobczak 						  NULL, "");
83cdcd52d4SBartosz Sobczak 	/*
84cdcd52d4SBartosz Sobczak 	 * debug mask setting
85cdcd52d4SBartosz Sobczak 	 */
8601fbb869SBartosz Sobczak 	SYSCTL_ADD_S32(&t_info->irdma_sysctl_ctx, irdma_oid_list,
87cdcd52d4SBartosz Sobczak 		       OID_AUTO, "debug", CTLFLAG_RWTUN, &rf->sc_dev.debug_mask,
88cdcd52d4SBartosz Sobczak 		       0, "irdma debug");
89cdcd52d4SBartosz Sobczak 
90cdcd52d4SBartosz Sobczak 	/*
91cdcd52d4SBartosz Sobczak 	 * RoCEv2/iWARP setting RoCEv2 the default mode
92cdcd52d4SBartosz Sobczak 	 */
9301fbb869SBartosz Sobczak 	t_info->roce_ena = 1;
9401fbb869SBartosz Sobczak 	SYSCTL_ADD_U8(&t_info->irdma_sysctl_ctx, irdma_oid_list, OID_AUTO,
9501fbb869SBartosz Sobczak 		      "roce_enable", CTLFLAG_RDTUN, &t_info->roce_ena, 0,
96cdcd52d4SBartosz Sobczak 		      "RoCEv2 mode enable");
97cdcd52d4SBartosz Sobczak 
98cdcd52d4SBartosz Sobczak 	rf->protocol_used = IRDMA_IWARP_PROTOCOL_ONLY;
9901fbb869SBartosz Sobczak 	if (t_info->roce_ena == 1)
100cdcd52d4SBartosz Sobczak 		rf->protocol_used = IRDMA_ROCE_PROTOCOL_ONLY;
10101fbb869SBartosz Sobczak 	else if (t_info->roce_ena != 0)
102cdcd52d4SBartosz Sobczak 		printf("%s:%d wrong roce_enable value (%d), using iWARP\n",
10301fbb869SBartosz Sobczak 		       __func__, __LINE__, t_info->roce_ena);
104cdcd52d4SBartosz Sobczak 	printf("%s:%d protocol: %s, roce_enable value: %d\n", __func__, __LINE__,
105cdcd52d4SBartosz Sobczak 	       (rf->protocol_used == IRDMA_IWARP_PROTOCOL_ONLY) ? "iWARP" : "RoCEv2",
10601fbb869SBartosz Sobczak 	       t_info->roce_ena);
107cdcd52d4SBartosz Sobczak 
10801fbb869SBartosz Sobczak 	snprintf(t_info->drv_ver, IRDMA_VER_LEN, "%s", irdma_driver_version);
10901fbb869SBartosz Sobczak 	SYSCTL_ADD_STRING(&t_info->irdma_sysctl_ctx, irdma_oid_list,
11001fbb869SBartosz Sobczak 			  OID_AUTO, "drv_ver", CTLFLAG_RDTUN, t_info->drv_ver,
111777e472cSBartosz Sobczak 			  IRDMA_VER_LEN, "driver version");
112777e472cSBartosz Sobczak 
113cdcd52d4SBartosz Sobczak 	irdma_dcqcn_tunables_init(rf);
11401fbb869SBartosz Sobczak 	irdma_sysctl_settings(rf);
115cdcd52d4SBartosz Sobczak }
116cdcd52d4SBartosz Sobczak 
117cdcd52d4SBartosz Sobczak /**
118cdcd52d4SBartosz Sobczak  * irdma_find_handler - obtain hdl object to identify pf
119cdcd52d4SBartosz Sobczak  * @p_dev: the peer interface structure
120cdcd52d4SBartosz Sobczak  */
121cdcd52d4SBartosz Sobczak static struct irdma_handler *
irdma_find_handler(struct ice_rdma_peer * p_dev)122cdcd52d4SBartosz Sobczak irdma_find_handler(struct ice_rdma_peer *p_dev)
123cdcd52d4SBartosz Sobczak {
124cdcd52d4SBartosz Sobczak 	struct irdma_handler *hdl;
125cdcd52d4SBartosz Sobczak 	unsigned long flags;
126cdcd52d4SBartosz Sobczak 
127cdcd52d4SBartosz Sobczak 	spin_lock_irqsave(&irdma_handler_lock, flags);
128cdcd52d4SBartosz Sobczak 	list_for_each_entry(hdl, &irdma_handlers, list) {
129cdcd52d4SBartosz Sobczak 		if (!hdl->iwdev->rf->peer_info)
130cdcd52d4SBartosz Sobczak 			continue;
131cdcd52d4SBartosz Sobczak 		if (hdl->iwdev->rf->peer_info->dev == p_dev->dev) {
132cdcd52d4SBartosz Sobczak 			spin_unlock_irqrestore(&irdma_handler_lock, flags);
133cdcd52d4SBartosz Sobczak 			return hdl;
134cdcd52d4SBartosz Sobczak 		}
135cdcd52d4SBartosz Sobczak 	}
136cdcd52d4SBartosz Sobczak 	spin_unlock_irqrestore(&irdma_handler_lock, flags);
137cdcd52d4SBartosz Sobczak 
138cdcd52d4SBartosz Sobczak 	return NULL;
139cdcd52d4SBartosz Sobczak }
140cdcd52d4SBartosz Sobczak 
141cdcd52d4SBartosz Sobczak /**
142cdcd52d4SBartosz Sobczak  * peer_to_iwdev - return iwdev based on peer
143cdcd52d4SBartosz Sobczak  * @peer: the peer interface structure
144cdcd52d4SBartosz Sobczak  */
145cdcd52d4SBartosz Sobczak static struct irdma_device *
peer_to_iwdev(struct ice_rdma_peer * peer)146cdcd52d4SBartosz Sobczak peer_to_iwdev(struct ice_rdma_peer *peer)
147cdcd52d4SBartosz Sobczak {
148cdcd52d4SBartosz Sobczak 	struct irdma_handler *hdl;
149cdcd52d4SBartosz Sobczak 
150cdcd52d4SBartosz Sobczak 	hdl = irdma_find_handler(peer);
151cdcd52d4SBartosz Sobczak 	if (!hdl) {
152cdcd52d4SBartosz Sobczak 		printf("%s:%d rdma handler not found\n", __func__, __LINE__);
153cdcd52d4SBartosz Sobczak 		return NULL;
154cdcd52d4SBartosz Sobczak 	}
155cdcd52d4SBartosz Sobczak 
156cdcd52d4SBartosz Sobczak 	return hdl->iwdev;
157cdcd52d4SBartosz Sobczak }
158cdcd52d4SBartosz Sobczak 
159cdcd52d4SBartosz Sobczak /**
160cdcd52d4SBartosz Sobczak  * irdma_get_qos_info - save qos info from parameters to internal struct
161cdcd52d4SBartosz Sobczak  * @l2params: destination, qos, tc, mtu info structure
162cdcd52d4SBartosz Sobczak  * @qos_info: source, DCB settings structure
163cdcd52d4SBartosz Sobczak  */
164cdcd52d4SBartosz Sobczak static void
irdma_get_qos_info(struct irdma_pci_f * rf,struct irdma_l2params * l2params,struct ice_qos_params * qos_info)16501fbb869SBartosz Sobczak irdma_get_qos_info(struct irdma_pci_f *rf, struct irdma_l2params *l2params,
16601fbb869SBartosz Sobczak 		   struct ice_qos_params *qos_info)
167cdcd52d4SBartosz Sobczak {
168cdcd52d4SBartosz Sobczak 	int i;
16901fbb869SBartosz Sobczak 	char txt[7][128] = {"", "", "", "", "", "", ""};
17001fbb869SBartosz Sobczak 	u8 len;
171cdcd52d4SBartosz Sobczak 
172cdcd52d4SBartosz Sobczak 	l2params->num_tc = qos_info->num_tc;
173cdcd52d4SBartosz Sobczak 	l2params->num_apps = qos_info->num_apps;
174cdcd52d4SBartosz Sobczak 	l2params->vsi_prio_type = qos_info->vsi_priority_type;
175cdcd52d4SBartosz Sobczak 	l2params->vsi_rel_bw = qos_info->vsi_relative_bw;
176cdcd52d4SBartosz Sobczak 	for (i = 0; i < l2params->num_tc; i++) {
177cdcd52d4SBartosz Sobczak 		l2params->tc_info[i].egress_virt_up =
178cdcd52d4SBartosz Sobczak 		    qos_info->tc_info[i].egress_virt_up;
179cdcd52d4SBartosz Sobczak 		l2params->tc_info[i].ingress_virt_up =
180cdcd52d4SBartosz Sobczak 		    qos_info->tc_info[i].ingress_virt_up;
181cdcd52d4SBartosz Sobczak 		l2params->tc_info[i].prio_type = qos_info->tc_info[i].prio_type;
182cdcd52d4SBartosz Sobczak 		l2params->tc_info[i].rel_bw = qos_info->tc_info[i].rel_bw;
183cdcd52d4SBartosz Sobczak 		l2params->tc_info[i].tc_ctx = qos_info->tc_info[i].tc_ctx;
184cdcd52d4SBartosz Sobczak 	}
185cdcd52d4SBartosz Sobczak 	for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++)
186cdcd52d4SBartosz Sobczak 		l2params->up2tc[i] = qos_info->up2tc[i];
187cdcd52d4SBartosz Sobczak 
188cdcd52d4SBartosz Sobczak 	if (qos_info->pfc_mode == IRDMA_QOS_MODE_DSCP) {
189cdcd52d4SBartosz Sobczak 		l2params->dscp_mode = true;
190cdcd52d4SBartosz Sobczak 		memcpy(l2params->dscp_map, qos_info->dscp_map, sizeof(l2params->dscp_map));
191cdcd52d4SBartosz Sobczak 	}
19201fbb869SBartosz Sobczak 	if (!(rf->sc_dev.debug_mask & IRDMA_DEBUG_DCB))
19301fbb869SBartosz Sobczak 		return;
19401fbb869SBartosz Sobczak 	for (i = 0; i < l2params->num_tc; i++) {
19501fbb869SBartosz Sobczak 		len = strlen(txt[0]);
19601fbb869SBartosz Sobczak 		snprintf(txt[0] + len, sizeof(txt[0]) - 5, " %d",
19701fbb869SBartosz Sobczak 			 l2params->tc_info[i].egress_virt_up);
19801fbb869SBartosz Sobczak 		len = strlen(txt[1]);
19901fbb869SBartosz Sobczak 		snprintf(txt[1] + len, sizeof(txt[1]) - 5, " %d",
20001fbb869SBartosz Sobczak 			 l2params->tc_info[i].ingress_virt_up);
20101fbb869SBartosz Sobczak 		len = strlen(txt[2]);
20201fbb869SBartosz Sobczak 		snprintf(txt[2] + len, sizeof(txt[2]) - 5, " %d",
20301fbb869SBartosz Sobczak 			 l2params->tc_info[i].prio_type);
20401fbb869SBartosz Sobczak 		len = strlen(txt[3]);
20501fbb869SBartosz Sobczak 		snprintf(txt[3] + len, sizeof(txt[3]) - 5, " %d",
20601fbb869SBartosz Sobczak 			 l2params->tc_info[i].rel_bw);
20701fbb869SBartosz Sobczak 		len = strlen(txt[4]);
20801fbb869SBartosz Sobczak 		snprintf(txt[4] + len, sizeof(txt[4]) - 5, " %lu",
20901fbb869SBartosz Sobczak 			 l2params->tc_info[i].tc_ctx);
21001fbb869SBartosz Sobczak 	}
21101fbb869SBartosz Sobczak 	len = strlen(txt[5]);
212cdcd52d4SBartosz Sobczak 	for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++)
21301fbb869SBartosz Sobczak 		len += snprintf(txt[5] + len, sizeof(txt[5]) - 5, " %d",
21401fbb869SBartosz Sobczak 				l2params->up2tc[i]);
21501fbb869SBartosz Sobczak 	len = strlen(txt[6]);
216cdcd52d4SBartosz Sobczak 	for (i = 0; i < IRDMA_DSCP_NUM_VAL; i++)
21701fbb869SBartosz Sobczak 		len += snprintf(txt[6] + len, sizeof(txt[6]) - 5, " %d",
21801fbb869SBartosz Sobczak 				l2params->dscp_map[i]);
21901fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "num_tc:          %d\n", l2params->num_tc);
22001fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "num_apps:        %d\n", l2params->num_apps);
22101fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "vsi_prio_type:   %d\n", l2params->vsi_prio_type);
22201fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "vsi_rel_bw:      %d\n", l2params->vsi_rel_bw);
22301fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "egress_virt_up: %s\n", txt[0]);
22401fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "ingress_virt_up:%s\n", txt[1]);
22501fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "prio_type: %s\n", txt[2]);
22601fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "rel_bw:    %s\n", txt[3]);
22701fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "tc_ctx:    %s\n", txt[4]);
22801fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "up2tc:     %s\n", txt[5]);
22901fbb869SBartosz Sobczak 	irdma_debug(&rf->sc_dev, IRDMA_DEBUG_DCB, "dscp_mode: %s\n", txt[6]);
230cdcd52d4SBartosz Sobczak 
23101fbb869SBartosz Sobczak 	irdma_debug_buf(&rf->sc_dev, IRDMA_DEBUG_DCB, "l2params", l2params, sizeof(*l2params));
232cdcd52d4SBartosz Sobczak }
233cdcd52d4SBartosz Sobczak 
234cdcd52d4SBartosz Sobczak /**
235cdcd52d4SBartosz Sobczak  * irdma_log_invalid_mtu - check mtu setting validity
236cdcd52d4SBartosz Sobczak  * @mtu: mtu value
237cdcd52d4SBartosz Sobczak  * @dev: hardware control device structure
238cdcd52d4SBartosz Sobczak  */
239cdcd52d4SBartosz Sobczak static void
irdma_log_invalid_mtu(u16 mtu,struct irdma_sc_dev * dev)240cdcd52d4SBartosz Sobczak irdma_log_invalid_mtu(u16 mtu, struct irdma_sc_dev *dev)
241cdcd52d4SBartosz Sobczak {
242cdcd52d4SBartosz Sobczak 	if (mtu < IRDMA_MIN_MTU_IPV4)
24335105900SBartosz Sobczak 		irdma_dev_warn(to_ibdev(dev),
24435105900SBartosz Sobczak 			       "MTU setting [%d] too low for RDMA traffic. Minimum MTU is 576 for IPv4\n",
24535105900SBartosz Sobczak 			       mtu);
246cdcd52d4SBartosz Sobczak 	else if (mtu < IRDMA_MIN_MTU_IPV6)
24735105900SBartosz Sobczak 		irdma_dev_warn(to_ibdev(dev),
248*5b5f7d0eSBartosz Sobczak 			       "MTU setting [%d] too low for RDMA traffic. Minimum MTU is 1280 for IPv6\n",
24935105900SBartosz Sobczak 			       mtu);
250cdcd52d4SBartosz Sobczak }
251cdcd52d4SBartosz Sobczak 
252cdcd52d4SBartosz Sobczak /**
25301fbb869SBartosz Sobczak  * irdma_get_event_name - convert type enum to string
25401fbb869SBartosz Sobczak  * @type: event type enum
25501fbb869SBartosz Sobczak  */
25601fbb869SBartosz Sobczak static const char *
irdma_get_event_name(enum ice_rdma_event_type type)25701fbb869SBartosz Sobczak irdma_get_event_name(enum ice_rdma_event_type type)
25801fbb869SBartosz Sobczak {
25901fbb869SBartosz Sobczak 	switch (type) {
26001fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_LINK_CHANGE:
26101fbb869SBartosz Sobczak 		return "LINK CHANGE";
26201fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_MTU_CHANGE:
26301fbb869SBartosz Sobczak 		return "MTU CHANGE";
26401fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_TC_CHANGE:
26501fbb869SBartosz Sobczak 		return "TC CHANGE";
26601fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_API_CHANGE:
26701fbb869SBartosz Sobczak 		return "API CHANGE";
26801fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_CRIT_ERR:
26901fbb869SBartosz Sobczak 		return "CRITICAL ERROR";
27001fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_RESET:
27101fbb869SBartosz Sobczak 		return "RESET";
27201fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_QSET_REGISTER:
27301fbb869SBartosz Sobczak 		return "QSET REGISTER";
27401fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_VSI_FILTER_UPDATE:
27501fbb869SBartosz Sobczak 		return "VSI FILTER UPDATE";
27601fbb869SBartosz Sobczak 	default:
27701fbb869SBartosz Sobczak 		return "UNKNOWN";
27801fbb869SBartosz Sobczak 	}
27901fbb869SBartosz Sobczak }
28001fbb869SBartosz Sobczak 
28101fbb869SBartosz Sobczak /**
282cdcd52d4SBartosz Sobczak  * irdma_event_handler - handling events from lan driver
283cdcd52d4SBartosz Sobczak  * @peer: the peer interface structure
284cdcd52d4SBartosz Sobczak  * @event: event info structure
285cdcd52d4SBartosz Sobczak  */
286cdcd52d4SBartosz Sobczak static void
irdma_event_handler(struct ice_rdma_peer * peer,struct ice_rdma_event * event)287cdcd52d4SBartosz Sobczak irdma_event_handler(struct ice_rdma_peer *peer, struct ice_rdma_event *event)
288cdcd52d4SBartosz Sobczak {
289cdcd52d4SBartosz Sobczak 	struct irdma_device *iwdev;
290cdcd52d4SBartosz Sobczak 	struct irdma_l2params l2params = {};
291cdcd52d4SBartosz Sobczak 
292cdcd52d4SBartosz Sobczak 	printf("%s:%d event_handler %s (%x) on pf %d (%d)\n", __func__, __LINE__,
29301fbb869SBartosz Sobczak 	       irdma_get_event_name(event->type),
294cfaab41cSJustin Hibbits 	       event->type, peer->pf_id, if_getdunit(peer->ifp));
295cdcd52d4SBartosz Sobczak 	iwdev = peer_to_iwdev(peer);
296cdcd52d4SBartosz Sobczak 	if (!iwdev) {
297cdcd52d4SBartosz Sobczak 		printf("%s:%d rdma device not found\n", __func__, __LINE__);
298cdcd52d4SBartosz Sobczak 		return;
299cdcd52d4SBartosz Sobczak 	}
300cdcd52d4SBartosz Sobczak 
301cdcd52d4SBartosz Sobczak 	switch (event->type) {
302cdcd52d4SBartosz Sobczak 	case ICE_RDMA_EVENT_LINK_CHANGE:
303cdcd52d4SBartosz Sobczak 		printf("%s:%d PF: %x (%x), state: %d, speed: %lu\n", __func__, __LINE__,
304cfaab41cSJustin Hibbits 		       peer->pf_id, if_getdunit(peer->ifp), event->linkstate,
305cfaab41cSJustin Hibbits 		       event->baudrate);
306cdcd52d4SBartosz Sobczak 		break;
307cdcd52d4SBartosz Sobczak 	case ICE_RDMA_EVENT_MTU_CHANGE:
308cdcd52d4SBartosz Sobczak 		if (iwdev->vsi.mtu != event->mtu) {
309cdcd52d4SBartosz Sobczak 			l2params.mtu = event->mtu;
310cdcd52d4SBartosz Sobczak 			l2params.mtu_changed = true;
311cdcd52d4SBartosz Sobczak 			irdma_log_invalid_mtu(l2params.mtu, &iwdev->rf->sc_dev);
312cdcd52d4SBartosz Sobczak 			irdma_change_l2params(&iwdev->vsi, &l2params);
313cdcd52d4SBartosz Sobczak 		}
314cdcd52d4SBartosz Sobczak 		break;
315cdcd52d4SBartosz Sobczak 	case ICE_RDMA_EVENT_TC_CHANGE:
316cdcd52d4SBartosz Sobczak 		/*
317cdcd52d4SBartosz Sobczak 		 * 1. check if it is pre or post 2. check if it is currently being done
318cdcd52d4SBartosz Sobczak 		 */
319cdcd52d4SBartosz Sobczak 		if (event->prep == iwdev->vsi.tc_change_pending) {
320cdcd52d4SBartosz Sobczak 			printf("%s:%d can't process %s TC change if TC change is %spending\n",
321cdcd52d4SBartosz Sobczak 			       __func__, __LINE__,
322cdcd52d4SBartosz Sobczak 			       event->prep ? "pre" : "post",
323cdcd52d4SBartosz Sobczak 			       event->prep ? " " : "not ");
324cdcd52d4SBartosz Sobczak 			goto done;
325cdcd52d4SBartosz Sobczak 		}
32601fbb869SBartosz Sobczak 		if (!atomic_inc_not_zero(&iwdev->rf->dev_ctx.event_rfcnt)) {
32701fbb869SBartosz Sobczak 			printf("%s:%d (%d) EVENT_TC_CHANGE received, but not processed %d\n",
32801fbb869SBartosz Sobczak 			       __func__, __LINE__, if_getdunit(peer->ifp),
32901fbb869SBartosz Sobczak 			       atomic_read(&iwdev->rf->dev_ctx.event_rfcnt));
33001fbb869SBartosz Sobczak 			break;
33101fbb869SBartosz Sobczak 		}
332cdcd52d4SBartosz Sobczak 		if (event->prep) {
333cdcd52d4SBartosz Sobczak 			iwdev->vsi.tc_change_pending = true;
334cdcd52d4SBartosz Sobczak 			irdma_sc_suspend_resume_qps(&iwdev->vsi, IRDMA_OP_SUSPEND);
335cdcd52d4SBartosz Sobczak 			wait_event_timeout(iwdev->suspend_wq,
336cdcd52d4SBartosz Sobczak 					   !atomic_read(&iwdev->vsi.qp_suspend_reqs),
337cdcd52d4SBartosz Sobczak 					   IRDMA_EVENT_TIMEOUT_MS * 10);
338cdcd52d4SBartosz Sobczak 			irdma_ws_reset(&iwdev->vsi);
339cdcd52d4SBartosz Sobczak 			printf("%s:%d TC change preparation done\n", __func__, __LINE__);
340cdcd52d4SBartosz Sobczak 		} else {
341cdcd52d4SBartosz Sobczak 			l2params.tc_changed = true;
34201fbb869SBartosz Sobczak 			irdma_get_qos_info(iwdev->rf, &l2params, &event->port_qos);
343cdcd52d4SBartosz Sobczak 			if (iwdev->rf->protocol_used != IRDMA_IWARP_PROTOCOL_ONLY)
344cdcd52d4SBartosz Sobczak 				iwdev->dcb_vlan_mode = l2params.num_tc > 1 && !l2params.dscp_mode;
345cdcd52d4SBartosz Sobczak 
346cdcd52d4SBartosz Sobczak 			irdma_check_fc_for_tc_update(&iwdev->vsi, &l2params);
347cdcd52d4SBartosz Sobczak 			irdma_change_l2params(&iwdev->vsi, &l2params);
348cdcd52d4SBartosz Sobczak 			printf("%s:%d TC change done\n", __func__, __LINE__);
349cdcd52d4SBartosz Sobczak 		}
35001fbb869SBartosz Sobczak 		atomic_dec(&iwdev->rf->dev_ctx.event_rfcnt);
351cdcd52d4SBartosz Sobczak 		break;
352cdcd52d4SBartosz Sobczak 	case ICE_RDMA_EVENT_CRIT_ERR:
35301fbb869SBartosz Sobczak 		if (event->oicr_reg & IRDMAPFINT_OICR_PE_CRITERR_M) {
35401fbb869SBartosz Sobczak 			u32 pe_criterr;
35501fbb869SBartosz Sobczak 
35601fbb869SBartosz Sobczak #define IRDMA_Q1_RESOURCE_ERR  0x0001024d
35701fbb869SBartosz Sobczak 			pe_criterr = readl(iwdev->rf->sc_dev.hw_regs[IRDMA_GLPE_CRITERR]);
35801fbb869SBartosz Sobczak 			if (pe_criterr != IRDMA_Q1_RESOURCE_ERR) {
35901fbb869SBartosz Sobczak 				irdma_pr_err("critical PE Error, GLPE_CRITERR=0x%08x\n",
36001fbb869SBartosz Sobczak 					     pe_criterr);
36101fbb869SBartosz Sobczak 				iwdev->rf->reset = true;
36201fbb869SBartosz Sobczak 			} else {
36301fbb869SBartosz Sobczak 				irdma_dev_warn(to_ibdev(&iwdev->rf->sc_dev),
36401fbb869SBartosz Sobczak 					       "Q1 Resource Check\n");
36501fbb869SBartosz Sobczak 			}
36601fbb869SBartosz Sobczak 		}
36701fbb869SBartosz Sobczak 		if (event->oicr_reg & IRDMAPFINT_OICR_HMC_ERR_M) {
36801fbb869SBartosz Sobczak 			irdma_pr_err("HMC Error\n");
36901fbb869SBartosz Sobczak 			iwdev->rf->reset = true;
37001fbb869SBartosz Sobczak 		}
37101fbb869SBartosz Sobczak 		if (iwdev->rf->reset)
37201fbb869SBartosz Sobczak 			iwdev->rf->gen_ops.request_reset(iwdev->rf);
37301fbb869SBartosz Sobczak 		break;
37401fbb869SBartosz Sobczak 	case ICE_RDMA_EVENT_RESET:
37501fbb869SBartosz Sobczak 		iwdev->rf->reset = true;
376cdcd52d4SBartosz Sobczak 		break;
377cdcd52d4SBartosz Sobczak 	default:
378cdcd52d4SBartosz Sobczak 		printf("%s:%d event type unsupported: %d\n", __func__, __LINE__, event->type);
379cdcd52d4SBartosz Sobczak 	}
380cdcd52d4SBartosz Sobczak done:
381cdcd52d4SBartosz Sobczak 	return;
382cdcd52d4SBartosz Sobczak }
383cdcd52d4SBartosz Sobczak 
384cdcd52d4SBartosz Sobczak /**
385cdcd52d4SBartosz Sobczak  * irdma_link_change - Callback for link state change
386cdcd52d4SBartosz Sobczak  * @peer: the peer interface structure
387cdcd52d4SBartosz Sobczak  * @linkstate: state of the link
388cdcd52d4SBartosz Sobczak  * @baudrate: speed of the link
389cdcd52d4SBartosz Sobczak  */
390cdcd52d4SBartosz Sobczak static void
irdma_link_change(struct ice_rdma_peer * peer,int linkstate,uint64_t baudrate)391cdcd52d4SBartosz Sobczak irdma_link_change(struct ice_rdma_peer *peer, int linkstate, uint64_t baudrate)
392cdcd52d4SBartosz Sobczak {
393cdcd52d4SBartosz Sobczak 	printf("%s:%d PF: %x (%x), state: %d, speed: %lu\n", __func__, __LINE__,
394cfaab41cSJustin Hibbits 	       peer->pf_id, if_getdunit(peer->ifp), linkstate, baudrate);
395cdcd52d4SBartosz Sobczak }
396cdcd52d4SBartosz Sobczak 
397cdcd52d4SBartosz Sobczak /**
398cdcd52d4SBartosz Sobczak  * irdma_finalize_task - Finish open or close phase in a separate thread
399cdcd52d4SBartosz Sobczak  * @context: instance holding peer and iwdev information
400cdcd52d4SBartosz Sobczak  *
401cdcd52d4SBartosz Sobczak  * Triggered from irdma_open or irdma_close to perform rt_init_hw or
402cdcd52d4SBartosz Sobczak  * rt_deinit_hw respectively. Does registration and unregistration of
403cdcd52d4SBartosz Sobczak  * the device.
404cdcd52d4SBartosz Sobczak  */
405cdcd52d4SBartosz Sobczak static void
irdma_finalize_task(void * context,int pending)406cdcd52d4SBartosz Sobczak irdma_finalize_task(void *context, int pending)
407cdcd52d4SBartosz Sobczak {
408cdcd52d4SBartosz Sobczak 	struct irdma_task_arg *task_arg = (struct irdma_task_arg *)context;
409cdcd52d4SBartosz Sobczak 	struct irdma_device *iwdev = task_arg->iwdev;
410cdcd52d4SBartosz Sobczak 	struct irdma_pci_f *rf = iwdev->rf;
411cdcd52d4SBartosz Sobczak 	struct ice_rdma_peer *peer = task_arg->peer;
412cdcd52d4SBartosz Sobczak 	struct irdma_l2params l2params = {{{0}}};
413cdcd52d4SBartosz Sobczak 	struct ice_rdma_request req = {0};
414cdcd52d4SBartosz Sobczak 	int status = 0;
415cdcd52d4SBartosz Sobczak 
416cdcd52d4SBartosz Sobczak 	if (iwdev->iw_status) {
41735105900SBartosz Sobczak 		irdma_debug(&rf->sc_dev, IRDMA_DEBUG_INIT,
41835105900SBartosz Sobczak 			    "Starting deferred closing %d (%d)\n",
419cfaab41cSJustin Hibbits 			    rf->peer_info->pf_id, if_getdunit(peer->ifp));
42001fbb869SBartosz Sobczak 		atomic_dec(&rf->dev_ctx.event_rfcnt);
42101fbb869SBartosz Sobczak 		wait_event_timeout(iwdev->suspend_wq,
42201fbb869SBartosz Sobczak 				   !atomic_read(&rf->dev_ctx.event_rfcnt),
42301fbb869SBartosz Sobczak 				   IRDMA_MAX_TIMEOUT);
42401fbb869SBartosz Sobczak 		if (atomic_read(&rf->dev_ctx.event_rfcnt) != 0) {
42501fbb869SBartosz Sobczak 			printf("%s:%d (%d) waiting for event_rfcnt (%d) timeout, proceed with unload\n",
42601fbb869SBartosz Sobczak 			       __func__, __LINE__, if_getdunit(peer->ifp),
42701fbb869SBartosz Sobczak 			       atomic_read(&rf->dev_ctx.event_rfcnt));
42801fbb869SBartosz Sobczak 		}
429cdcd52d4SBartosz Sobczak 		irdma_dereg_ipaddr_event_cb(rf);
430cdcd52d4SBartosz Sobczak 		irdma_ib_unregister_device(iwdev);
431cdcd52d4SBartosz Sobczak 		req.type = ICE_RDMA_EVENT_VSI_FILTER_UPDATE;
432cdcd52d4SBartosz Sobczak 		req.enable_filter = false;
433cdcd52d4SBartosz Sobczak 		IRDMA_DI_REQ_HANDLER(peer, &req);
43435105900SBartosz Sobczak 		irdma_cleanup_dead_qps(&iwdev->vsi);
435cdcd52d4SBartosz Sobczak 		irdma_rt_deinit_hw(iwdev);
436cdcd52d4SBartosz Sobczak 	} else {
43735105900SBartosz Sobczak 		irdma_debug(&rf->sc_dev, IRDMA_DEBUG_INIT,
43835105900SBartosz Sobczak 			    "Starting deferred opening %d (%d)\n",
439cfaab41cSJustin Hibbits 			    rf->peer_info->pf_id, if_getdunit(peer->ifp));
44001fbb869SBartosz Sobczak 		irdma_get_qos_info(iwdev->rf, &l2params, &peer->initial_qos_info);
441cdcd52d4SBartosz Sobczak 		if (iwdev->rf->protocol_used != IRDMA_IWARP_PROTOCOL_ONLY)
442cdcd52d4SBartosz Sobczak 			iwdev->dcb_vlan_mode = l2params.num_tc > 1 && !l2params.dscp_mode;
443cdcd52d4SBartosz Sobczak 
44435105900SBartosz Sobczak 		l2params.mtu = peer->mtu;
445cdcd52d4SBartosz Sobczak 		status = irdma_rt_init_hw(iwdev, &l2params);
446cdcd52d4SBartosz Sobczak 		if (status) {
447cdcd52d4SBartosz Sobczak 			irdma_pr_err("RT init failed %d\n", status);
448cdcd52d4SBartosz Sobczak 			ib_dealloc_device(&iwdev->ibdev);
449cdcd52d4SBartosz Sobczak 			return;
450cdcd52d4SBartosz Sobczak 		}
451cdcd52d4SBartosz Sobczak 		status = irdma_ib_register_device(iwdev);
452cdcd52d4SBartosz Sobczak 		if (status) {
453cdcd52d4SBartosz Sobczak 			irdma_pr_err("Registration failed %d\n", status);
454cdcd52d4SBartosz Sobczak 			irdma_rt_deinit_hw(iwdev);
455cdcd52d4SBartosz Sobczak 			ib_dealloc_device(&iwdev->ibdev);
456cdcd52d4SBartosz Sobczak 		}
45701fbb869SBartosz Sobczak 		irdma_sw_stats_tunables_init(rf);
458cdcd52d4SBartosz Sobczak 		req.type = ICE_RDMA_EVENT_VSI_FILTER_UPDATE;
459cdcd52d4SBartosz Sobczak 		req.enable_filter = true;
460cdcd52d4SBartosz Sobczak 		IRDMA_DI_REQ_HANDLER(peer, &req);
461cdcd52d4SBartosz Sobczak 		irdma_reg_ipaddr_event_cb(rf);
46201fbb869SBartosz Sobczak 		atomic_inc(&rf->dev_ctx.event_rfcnt);
46335105900SBartosz Sobczak 		irdma_debug(&rf->sc_dev, IRDMA_DEBUG_INIT,
46435105900SBartosz Sobczak 			    "Deferred opening finished %d (%d)\n",
465cfaab41cSJustin Hibbits 			    rf->peer_info->pf_id, if_getdunit(peer->ifp));
466cdcd52d4SBartosz Sobczak 	}
467cdcd52d4SBartosz Sobczak }
468cdcd52d4SBartosz Sobczak 
469cdcd52d4SBartosz Sobczak /**
470cdcd52d4SBartosz Sobczak  * irdma_alloc_pcidev - allocate memory for pcidev and populate data
471cdcd52d4SBartosz Sobczak  * @peer: the new peer interface structure
472cdcd52d4SBartosz Sobczak  * @rf: RDMA PCI function
473cdcd52d4SBartosz Sobczak  */
474cdcd52d4SBartosz Sobczak static int
irdma_alloc_pcidev(struct ice_rdma_peer * peer,struct irdma_pci_f * rf)475cdcd52d4SBartosz Sobczak irdma_alloc_pcidev(struct ice_rdma_peer *peer, struct irdma_pci_f *rf)
476cdcd52d4SBartosz Sobczak {
477cdcd52d4SBartosz Sobczak 	rf->pcidev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
478cdcd52d4SBartosz Sobczak 	if (!rf->pcidev) {
479cdcd52d4SBartosz Sobczak 		return -ENOMEM;
480cdcd52d4SBartosz Sobczak 	}
481cdcd52d4SBartosz Sobczak 	if (linux_pci_attach_device(rf->dev_ctx.dev, NULL, NULL, rf->pcidev))
482cdcd52d4SBartosz Sobczak 		return -ENOMEM;
483cdcd52d4SBartosz Sobczak 
484cdcd52d4SBartosz Sobczak 	return 0;
485cdcd52d4SBartosz Sobczak }
486cdcd52d4SBartosz Sobczak 
487cdcd52d4SBartosz Sobczak /**
488cdcd52d4SBartosz Sobczak  * irdma_dealloc_pcidev - deallocate memory for pcidev
489cdcd52d4SBartosz Sobczak  * @rf: RDMA PCI function
490cdcd52d4SBartosz Sobczak  */
491cdcd52d4SBartosz Sobczak static void
irdma_dealloc_pcidev(struct irdma_pci_f * rf)492cdcd52d4SBartosz Sobczak irdma_dealloc_pcidev(struct irdma_pci_f *rf)
493cdcd52d4SBartosz Sobczak {
494cdcd52d4SBartosz Sobczak 	linux_pci_detach_device(rf->pcidev);
495cdcd52d4SBartosz Sobczak 	kfree(rf->pcidev);
496cdcd52d4SBartosz Sobczak }
497cdcd52d4SBartosz Sobczak 
498cdcd52d4SBartosz Sobczak /**
499cdcd52d4SBartosz Sobczak  * irdma_fill_device_info - assign initial values to rf variables
500cdcd52d4SBartosz Sobczak  * @iwdev: irdma device
501cdcd52d4SBartosz Sobczak  * @peer: the peer interface structure
502cdcd52d4SBartosz Sobczak  */
503cdcd52d4SBartosz Sobczak static void
irdma_fill_device_info(struct irdma_device * iwdev,struct ice_rdma_peer * peer)504cdcd52d4SBartosz Sobczak irdma_fill_device_info(struct irdma_device *iwdev,
505cdcd52d4SBartosz Sobczak 		       struct ice_rdma_peer *peer)
506cdcd52d4SBartosz Sobczak {
507cdcd52d4SBartosz Sobczak 	struct irdma_pci_f *rf = iwdev->rf;
508cdcd52d4SBartosz Sobczak 
509cdcd52d4SBartosz Sobczak 	rf->peer_info = peer;
510cdcd52d4SBartosz Sobczak 	rf->gen_ops.register_qset = irdma_register_qset;
511cdcd52d4SBartosz Sobczak 	rf->gen_ops.unregister_qset = irdma_unregister_qset;
512cdcd52d4SBartosz Sobczak 
513cdcd52d4SBartosz Sobczak 	rf->rdma_ver = IRDMA_GEN_2;
514cdcd52d4SBartosz Sobczak 	rf->sc_dev.hw_attrs.uk_attrs.hw_rev = IRDMA_GEN_2;
515cdcd52d4SBartosz Sobczak 	rf->rsrc_profile = IRDMA_HMC_PROFILE_DEFAULT;
516cdcd52d4SBartosz Sobczak 	rf->rst_to = IRDMA_RST_TIMEOUT_HZ;
517cdcd52d4SBartosz Sobczak 	rf->check_fc = irdma_check_fc_for_qp;
51835105900SBartosz Sobczak 	rf->gen_ops.request_reset = irdma_request_reset;
519cdcd52d4SBartosz Sobczak 	irdma_set_rf_user_cfg_params(rf);
520cdcd52d4SBartosz Sobczak 
521cdcd52d4SBartosz Sobczak 	rf->default_vsi.vsi_idx = peer->pf_vsi_num;
522cdcd52d4SBartosz Sobczak 	rf->dev_ctx.dev = peer->dev;
523cdcd52d4SBartosz Sobczak 	rf->dev_ctx.mem_bus_space_tag = rman_get_bustag(peer->pci_mem);
524cdcd52d4SBartosz Sobczak 	rf->dev_ctx.mem_bus_space_handle = rman_get_bushandle(peer->pci_mem);
525cdcd52d4SBartosz Sobczak 	rf->dev_ctx.mem_bus_space_size = rman_get_size(peer->pci_mem);
526cdcd52d4SBartosz Sobczak 
527cdcd52d4SBartosz Sobczak 	rf->hw.dev_context = &rf->dev_ctx;
528cdcd52d4SBartosz Sobczak 	rf->hw.hw_addr = (u8 *)rman_get_virtual(peer->pci_mem);
529cdcd52d4SBartosz Sobczak 	rf->msix_count = peer->msix.count;
530cdcd52d4SBartosz Sobczak 	rf->msix_info.entry = peer->msix.base;
531cdcd52d4SBartosz Sobczak 	rf->msix_info.vector = peer->msix.count;
532cdcd52d4SBartosz Sobczak 	printf("%s:%d msix_info: %d %d %d\n", __func__, __LINE__,
533cdcd52d4SBartosz Sobczak 	       rf->msix_count, rf->msix_info.entry, rf->msix_info.vector);
534cdcd52d4SBartosz Sobczak 
535cdcd52d4SBartosz Sobczak 	rf->iwdev = iwdev;
536cdcd52d4SBartosz Sobczak 	iwdev->netdev = peer->ifp;
537cdcd52d4SBartosz Sobczak 	iwdev->init_state = INITIAL_STATE;
538cdcd52d4SBartosz Sobczak 	iwdev->vsi_num = peer->pf_vsi_num;
539cdcd52d4SBartosz Sobczak 	iwdev->rcv_wnd = IRDMA_CM_DEFAULT_RCV_WND_SCALED;
540cdcd52d4SBartosz Sobczak 	iwdev->rcv_wscale = IRDMA_CM_DEFAULT_RCV_WND_SCALE;
541cdcd52d4SBartosz Sobczak 	iwdev->roce_cwnd = IRDMA_ROCE_CWND_DEFAULT;
542cdcd52d4SBartosz Sobczak 	iwdev->roce_ackcreds = IRDMA_ROCE_ACKCREDS_DEFAULT;
54335105900SBartosz Sobczak 	iwdev->roce_rtomin = 5;
544cdcd52d4SBartosz Sobczak 
545cdcd52d4SBartosz Sobczak 	if (rf->protocol_used == IRDMA_ROCE_PROTOCOL_ONLY) {
546cdcd52d4SBartosz Sobczak 		iwdev->roce_mode = true;
547cdcd52d4SBartosz Sobczak 	}
548cdcd52d4SBartosz Sobczak }
549cdcd52d4SBartosz Sobczak 
550cdcd52d4SBartosz Sobczak /**
551cdcd52d4SBartosz Sobczak  * irdma_probe - Callback to probe a new RDMA peer device
552cdcd52d4SBartosz Sobczak  * @peer: the new peer interface structure
553cdcd52d4SBartosz Sobczak  *
554cdcd52d4SBartosz Sobczak  * Callback implementing the RDMA_PROBE function. Called by the ice driver to
555cdcd52d4SBartosz Sobczak  * notify the RDMA client driver that a new device has been created
556cdcd52d4SBartosz Sobczak  */
557cdcd52d4SBartosz Sobczak static int
irdma_probe(struct ice_rdma_peer * peer)558cdcd52d4SBartosz Sobczak irdma_probe(struct ice_rdma_peer *peer)
559cdcd52d4SBartosz Sobczak {
560cdcd52d4SBartosz Sobczak 	struct irdma_device *iwdev;
561cdcd52d4SBartosz Sobczak 	struct irdma_pci_f *rf;
562cdcd52d4SBartosz Sobczak 	struct irdma_handler *hdl;
563cdcd52d4SBartosz Sobczak 	int err = 0;
564cdcd52d4SBartosz Sobczak 
565e602a30bSEric Joyner 	irdma_pr_info("probe: irdma-%s peer=%p, peer->pf_id=%d, peer->ifp=%p, peer->ifp->if_dunit=%d, peer->pci_mem->r_bustag=%p\n",
566cdcd52d4SBartosz Sobczak 		      irdma_driver_version, peer, peer->pf_id, peer->ifp,
567cfaab41cSJustin Hibbits 		      if_getdunit(peer->ifp), (void *)(uintptr_t)peer->pci_mem->r_bustag);
568cdcd52d4SBartosz Sobczak 
569cdcd52d4SBartosz Sobczak 	hdl = irdma_find_handler(peer);
570cdcd52d4SBartosz Sobczak 	if (hdl)
571cdcd52d4SBartosz Sobczak 		return -EBUSY;
572cdcd52d4SBartosz Sobczak 
573cdcd52d4SBartosz Sobczak 	hdl = kzalloc(sizeof(*hdl), GFP_KERNEL);
574cdcd52d4SBartosz Sobczak 	if (!hdl)
575cdcd52d4SBartosz Sobczak 		return -ENOMEM;
576cdcd52d4SBartosz Sobczak 
577cdcd52d4SBartosz Sobczak 	iwdev = (struct irdma_device *)ib_alloc_device(sizeof(*iwdev));
578cdcd52d4SBartosz Sobczak 	if (!iwdev) {
579cdcd52d4SBartosz Sobczak 		kfree(hdl);
580cdcd52d4SBartosz Sobczak 		return -ENOMEM;
581cdcd52d4SBartosz Sobczak 	}
582cdcd52d4SBartosz Sobczak 
583cdcd52d4SBartosz Sobczak 	iwdev->rf = kzalloc(sizeof(*rf), GFP_KERNEL);
584cdcd52d4SBartosz Sobczak 	if (!iwdev->rf) {
585cdcd52d4SBartosz Sobczak 		ib_dealloc_device(&iwdev->ibdev);
586cdcd52d4SBartosz Sobczak 		kfree(hdl);
587cdcd52d4SBartosz Sobczak 		return -ENOMEM;
588cdcd52d4SBartosz Sobczak 	}
589cdcd52d4SBartosz Sobczak 	hdl->iwdev = iwdev;
590cdcd52d4SBartosz Sobczak 	iwdev->hdl = hdl;
591cdcd52d4SBartosz Sobczak 
592cfaab41cSJustin Hibbits 	irdma_init_tunable(iwdev->rf, if_getdunit(peer->ifp));
593cdcd52d4SBartosz Sobczak 	irdma_fill_device_info(iwdev, peer);
594cdcd52d4SBartosz Sobczak 	rf = iwdev->rf;
595cdcd52d4SBartosz Sobczak 
596cdcd52d4SBartosz Sobczak 	if (irdma_alloc_pcidev(peer, rf))
597cdcd52d4SBartosz Sobczak 		goto err_pcidev;
598cdcd52d4SBartosz Sobczak 
599cdcd52d4SBartosz Sobczak 	irdma_add_handler(hdl);
600cdcd52d4SBartosz Sobczak 
601cdcd52d4SBartosz Sobczak 	if (irdma_ctrl_init_hw(rf)) {
602cdcd52d4SBartosz Sobczak 		err = -EIO;
603cdcd52d4SBartosz Sobczak 		goto err_ctrl_init;
604cdcd52d4SBartosz Sobczak 	}
605cdcd52d4SBartosz Sobczak 
606cdcd52d4SBartosz Sobczak 	rf->dev_ctx.task_arg.peer = peer;
607cdcd52d4SBartosz Sobczak 	rf->dev_ctx.task_arg.iwdev = iwdev;
608cdcd52d4SBartosz Sobczak 	rf->dev_ctx.task_arg.peer = peer;
609cdcd52d4SBartosz Sobczak 
610cdcd52d4SBartosz Sobczak 	TASK_INIT(&hdl->deferred_task, 0, irdma_finalize_task, &rf->dev_ctx.task_arg);
611cdcd52d4SBartosz Sobczak 	hdl->deferred_tq = taskqueue_create_fast("irdma_defer",
612cdcd52d4SBartosz Sobczak 						 M_NOWAIT, taskqueue_thread_enqueue,
613cdcd52d4SBartosz Sobczak 						 &hdl->deferred_tq);
614cdcd52d4SBartosz Sobczak 	taskqueue_start_threads(&hdl->deferred_tq, 1, PI_NET, "irdma_defer_t");
615cdcd52d4SBartosz Sobczak 
616cdcd52d4SBartosz Sobczak 	taskqueue_enqueue(hdl->deferred_tq, &hdl->deferred_task);
617cdcd52d4SBartosz Sobczak 
618cdcd52d4SBartosz Sobczak 	return 0;
619cdcd52d4SBartosz Sobczak 
620cdcd52d4SBartosz Sobczak err_ctrl_init:
621cdcd52d4SBartosz Sobczak 	irdma_del_handler(hdl);
622cdcd52d4SBartosz Sobczak 	irdma_dealloc_pcidev(rf);
623cdcd52d4SBartosz Sobczak err_pcidev:
624cdcd52d4SBartosz Sobczak 	kfree(iwdev->rf);
625cdcd52d4SBartosz Sobczak 	ib_dealloc_device(&iwdev->ibdev);
626cdcd52d4SBartosz Sobczak 	kfree(hdl);
627cdcd52d4SBartosz Sobczak 
628cdcd52d4SBartosz Sobczak 	return err;
629cdcd52d4SBartosz Sobczak }
630cdcd52d4SBartosz Sobczak 
631cdcd52d4SBartosz Sobczak /**
632cdcd52d4SBartosz Sobczak  * irdma_remove - Callback to remove an RDMA peer device
633cdcd52d4SBartosz Sobczak  * @peer: the new peer interface structure
634cdcd52d4SBartosz Sobczak  *
635cdcd52d4SBartosz Sobczak  * Callback implementing the RDMA_REMOVE function. Called by the ice driver to
636cdcd52d4SBartosz Sobczak  * notify the RDMA client driver that the device wille be delated
637cdcd52d4SBartosz Sobczak  */
638cdcd52d4SBartosz Sobczak static int
irdma_remove(struct ice_rdma_peer * peer)639cdcd52d4SBartosz Sobczak irdma_remove(struct ice_rdma_peer *peer)
640cdcd52d4SBartosz Sobczak {
641cdcd52d4SBartosz Sobczak 	struct irdma_handler *hdl;
642cdcd52d4SBartosz Sobczak 	struct irdma_device *iwdev;
643cdcd52d4SBartosz Sobczak 
64435105900SBartosz Sobczak 	irdma_debug((struct irdma_sc_dev *)NULL, IRDMA_DEBUG_INIT,
645cfaab41cSJustin Hibbits 		    "removing %s irdma%d\n", __func__, if_getdunit(peer->ifp));
646cdcd52d4SBartosz Sobczak 
647cdcd52d4SBartosz Sobczak 	hdl = irdma_find_handler(peer);
648cdcd52d4SBartosz Sobczak 	if (!hdl)
649cdcd52d4SBartosz Sobczak 		return 0;
650cdcd52d4SBartosz Sobczak 
651cdcd52d4SBartosz Sobczak 	iwdev = hdl->iwdev;
652cdcd52d4SBartosz Sobczak 
653cdcd52d4SBartosz Sobczak 	if (iwdev->vsi.tc_change_pending) {
654cdcd52d4SBartosz Sobczak 		iwdev->vsi.tc_change_pending = false;
655cdcd52d4SBartosz Sobczak 		irdma_sc_suspend_resume_qps(&iwdev->vsi, IRDMA_OP_RESUME);
656cdcd52d4SBartosz Sobczak 	}
657cdcd52d4SBartosz Sobczak 
658cdcd52d4SBartosz Sobczak 	taskqueue_enqueue(hdl->deferred_tq, &hdl->deferred_task);
659cdcd52d4SBartosz Sobczak 
660cdcd52d4SBartosz Sobczak 	taskqueue_drain(hdl->deferred_tq, &hdl->deferred_task);
661cdcd52d4SBartosz Sobczak 	taskqueue_free(hdl->deferred_tq);
662cdcd52d4SBartosz Sobczak 	hdl->iwdev->rf->dev_ctx.task_arg.iwdev = NULL;
663cdcd52d4SBartosz Sobczak 	hdl->iwdev->rf->dev_ctx.task_arg.peer = NULL;
664cdcd52d4SBartosz Sobczak 
665cdcd52d4SBartosz Sobczak 	sysctl_ctx_free(&iwdev->rf->tun_info.irdma_sysctl_ctx);
666cdcd52d4SBartosz Sobczak 	hdl->iwdev->rf->tun_info.irdma_sysctl_tree = NULL;
66701fbb869SBartosz Sobczak 	hdl->iwdev->rf->tun_info.sws_sysctl_tree = NULL;
668cdcd52d4SBartosz Sobczak 
669cdcd52d4SBartosz Sobczak 	irdma_ctrl_deinit_hw(iwdev->rf);
670cdcd52d4SBartosz Sobczak 
671cdcd52d4SBartosz Sobczak 	irdma_dealloc_pcidev(iwdev->rf);
672cdcd52d4SBartosz Sobczak 
673cdcd52d4SBartosz Sobczak 	irdma_del_handler(iwdev->hdl);
674cdcd52d4SBartosz Sobczak 	kfree(iwdev->hdl);
675cdcd52d4SBartosz Sobczak 	kfree(iwdev->rf);
676cdcd52d4SBartosz Sobczak 	ib_dealloc_device(&iwdev->ibdev);
67735105900SBartosz Sobczak 	irdma_pr_info("IRDMA hardware deinitialization complete irdma%d\n",
678cfaab41cSJustin Hibbits 		      if_getdunit(peer->ifp));
679cdcd52d4SBartosz Sobczak 
680cdcd52d4SBartosz Sobczak 	return 0;
681cdcd52d4SBartosz Sobczak }
682cdcd52d4SBartosz Sobczak 
683cdcd52d4SBartosz Sobczak /**
68401fbb869SBartosz Sobczak  * irdma_open - Callback for operation open for RDMA device
68501fbb869SBartosz Sobczak  * @peer: the new peer interface structure
68601fbb869SBartosz Sobczak  *
68701fbb869SBartosz Sobczak  * Callback implementing the RDMA_OPEN function. Called by the ice driver to
68801fbb869SBartosz Sobczak  * notify the RDMA client driver that a new device has been initialized.
68901fbb869SBartosz Sobczak  */
69001fbb869SBartosz Sobczak static int
irdma_open(struct ice_rdma_peer * peer)69101fbb869SBartosz Sobczak irdma_open(struct ice_rdma_peer *peer)
69201fbb869SBartosz Sobczak {
69301fbb869SBartosz Sobczak 	struct irdma_device *iwdev;
69401fbb869SBartosz Sobczak 	struct ice_rdma_event event = {0};
69501fbb869SBartosz Sobczak 
69601fbb869SBartosz Sobczak 	iwdev = peer_to_iwdev(peer);
69701fbb869SBartosz Sobczak 	if (iwdev) {
69801fbb869SBartosz Sobczak 		event.type = ICE_RDMA_EVENT_MTU_CHANGE;
69901fbb869SBartosz Sobczak 		event.mtu = peer->mtu;
70001fbb869SBartosz Sobczak 
70101fbb869SBartosz Sobczak 		irdma_event_handler(peer, &event);
70201fbb869SBartosz Sobczak 	} else {
70301fbb869SBartosz Sobczak 		irdma_probe(peer);
70401fbb869SBartosz Sobczak 	}
70501fbb869SBartosz Sobczak 
70601fbb869SBartosz Sobczak 	return 0;
70701fbb869SBartosz Sobczak }
70801fbb869SBartosz Sobczak 
70901fbb869SBartosz Sobczak /**
71001fbb869SBartosz Sobczak  * irdma_close - Callback to notify that a peer device is down
71101fbb869SBartosz Sobczak  * @peer: the RDMA peer device being stopped
71201fbb869SBartosz Sobczak  *
71301fbb869SBartosz Sobczak  * Callback implementing the RDMA_CLOSE function. Called by the ice driver to
71401fbb869SBartosz Sobczak  * notify the RDMA client driver that a peer device is being stopped.
71501fbb869SBartosz Sobczak  */
71601fbb869SBartosz Sobczak static int
irdma_close(struct ice_rdma_peer * peer)71701fbb869SBartosz Sobczak irdma_close(struct ice_rdma_peer *peer)
71801fbb869SBartosz Sobczak {
71901fbb869SBartosz Sobczak 	/*
72001fbb869SBartosz Sobczak 	 * This is called when ifconfig down or pf-reset is about to happen.
72101fbb869SBartosz Sobczak 	 */
72201fbb869SBartosz Sobczak 	struct irdma_device *iwdev;
72301fbb869SBartosz Sobczak 
72401fbb869SBartosz Sobczak 	iwdev = peer_to_iwdev(peer);
72501fbb869SBartosz Sobczak 	if (iwdev && iwdev->rf->reset)
72601fbb869SBartosz Sobczak 		irdma_remove(peer);
72701fbb869SBartosz Sobczak 
72801fbb869SBartosz Sobczak 	return 0;
72901fbb869SBartosz Sobczak }
73001fbb869SBartosz Sobczak 
73101fbb869SBartosz Sobczak /**
732cdcd52d4SBartosz Sobczak  * irdma_prep_for_unregister - ensure the driver is ready to unregister
733cdcd52d4SBartosz Sobczak  */
734cdcd52d4SBartosz Sobczak static void
irdma_prep_for_unregister(void)735ee6c09acSDimitry Andric irdma_prep_for_unregister(void)
736cdcd52d4SBartosz Sobczak {
737cdcd52d4SBartosz Sobczak 	struct irdma_handler *hdl;
738cdcd52d4SBartosz Sobczak 	unsigned long flags;
739cdcd52d4SBartosz Sobczak 	bool hdl_valid;
740cdcd52d4SBartosz Sobczak 
741cdcd52d4SBartosz Sobczak 	do {
742cdcd52d4SBartosz Sobczak 		hdl_valid = false;
743cdcd52d4SBartosz Sobczak 		spin_lock_irqsave(&irdma_handler_lock, flags);
744cdcd52d4SBartosz Sobczak 		list_for_each_entry(hdl, &irdma_handlers, list) {
745cdcd52d4SBartosz Sobczak 			if (!hdl->iwdev->rf->peer_info)
746cdcd52d4SBartosz Sobczak 				continue;
747cdcd52d4SBartosz Sobczak 			hdl_valid = true;
748cdcd52d4SBartosz Sobczak 			break;
749cdcd52d4SBartosz Sobczak 		}
750cdcd52d4SBartosz Sobczak 		spin_unlock_irqrestore(&irdma_handler_lock, flags);
751cdcd52d4SBartosz Sobczak 		if (!hdl || !hdl_valid)
752cdcd52d4SBartosz Sobczak 			break;
753cdcd52d4SBartosz Sobczak 		IRDMA_CLOSE(hdl->iwdev->rf->peer_info);
754cdcd52d4SBartosz Sobczak 		IRDMA_REMOVE(hdl->iwdev->rf->peer_info);
755cdcd52d4SBartosz Sobczak 	} while (1);
756cdcd52d4SBartosz Sobczak }
757cdcd52d4SBartosz Sobczak 
758cdcd52d4SBartosz Sobczak static kobj_method_t irdma_methods[] = {
759cdcd52d4SBartosz Sobczak 	KOBJMETHOD(irdma_probe, irdma_probe),
760cdcd52d4SBartosz Sobczak 	    KOBJMETHOD(irdma_open, irdma_open),
761cdcd52d4SBartosz Sobczak 	    KOBJMETHOD(irdma_close, irdma_close),
762cdcd52d4SBartosz Sobczak 	    KOBJMETHOD(irdma_remove, irdma_remove),
763cdcd52d4SBartosz Sobczak 	    KOBJMETHOD(irdma_link_change, irdma_link_change),
764cdcd52d4SBartosz Sobczak 	    KOBJMETHOD(irdma_event_handler, irdma_event_handler),
765cdcd52d4SBartosz Sobczak 	    KOBJMETHOD_END
766cdcd52d4SBartosz Sobczak };
767cdcd52d4SBartosz Sobczak 
768cdcd52d4SBartosz Sobczak /* declare irdma_class which extends the ice_rdma_di class */
769cdcd52d4SBartosz Sobczak DEFINE_CLASS_1(irdma, irdma_class, irdma_methods, sizeof(struct ice_rdma_peer), ice_rdma_di_class);
770cdcd52d4SBartosz Sobczak 
771cdcd52d4SBartosz Sobczak static struct ice_rdma_info irdma_info = {
772cdcd52d4SBartosz Sobczak 	.major_version = ICE_RDMA_MAJOR_VERSION,
773cdcd52d4SBartosz Sobczak 	.minor_version = ICE_RDMA_MINOR_VERSION,
774cdcd52d4SBartosz Sobczak 	.patch_version = ICE_RDMA_PATCH_VERSION,
775cdcd52d4SBartosz Sobczak 	.rdma_class = &irdma_class,
776cdcd52d4SBartosz Sobczak };
777cdcd52d4SBartosz Sobczak 
778cdcd52d4SBartosz Sobczak /**
779cdcd52d4SBartosz Sobczak  * irdma_module_event_handler - Module event handler callback
780cdcd52d4SBartosz Sobczak  * @mod: unused mod argument
781cdcd52d4SBartosz Sobczak  * @what: the module event to handle
782cdcd52d4SBartosz Sobczak  * @arg: unused module event argument
783cdcd52d4SBartosz Sobczak  *
784cdcd52d4SBartosz Sobczak  * Callback used by the FreeBSD module stack to notify the driver of module
785cdcd52d4SBartosz Sobczak  * events. Used to implement custom handling for certain module events such as
786cdcd52d4SBartosz Sobczak  * load and unload.
787cdcd52d4SBartosz Sobczak  */
788cdcd52d4SBartosz Sobczak static int
irdma_module_event_handler(module_t __unused mod,int what,void __unused * arg)789cdcd52d4SBartosz Sobczak irdma_module_event_handler(module_t __unused mod, int what, void __unused * arg)
790cdcd52d4SBartosz Sobczak {
791cdcd52d4SBartosz Sobczak 	switch (what) {
792cdcd52d4SBartosz Sobczak 	case MOD_LOAD:
793cdcd52d4SBartosz Sobczak 		printf("Loading irdma module\n");
794cdcd52d4SBartosz Sobczak 		return ice_rdma_register(&irdma_info);
795cdcd52d4SBartosz Sobczak 	case MOD_UNLOAD:
796cdcd52d4SBartosz Sobczak 		printf("Unloading irdma module\n");
797cdcd52d4SBartosz Sobczak 		irdma_prep_for_unregister();
798cdcd52d4SBartosz Sobczak 		ice_rdma_unregister();
799cdcd52d4SBartosz Sobczak 		return (0);
800cdcd52d4SBartosz Sobczak 	default:
801cdcd52d4SBartosz Sobczak 		return (EOPNOTSUPP);
802cdcd52d4SBartosz Sobczak 	}
803cdcd52d4SBartosz Sobczak 
804cdcd52d4SBartosz Sobczak 	return (0);
805cdcd52d4SBartosz Sobczak }
806cdcd52d4SBartosz Sobczak 
807cdcd52d4SBartosz Sobczak static moduledata_t irdma_moduledata = {
808cdcd52d4SBartosz Sobczak 	"irdma",
809cdcd52d4SBartosz Sobczak 	    irdma_module_event_handler,
810cdcd52d4SBartosz Sobczak 	    NULL
811cdcd52d4SBartosz Sobczak };
812cdcd52d4SBartosz Sobczak 
813cdcd52d4SBartosz Sobczak DECLARE_MODULE(irdma, irdma_moduledata, SI_SUB_LAST, SI_ORDER_ANY);
814cdcd52d4SBartosz Sobczak MODULE_VERSION(irdma, 1);
815cdcd52d4SBartosz Sobczak MODULE_DEPEND(irdma, ice, 1, 1, 1);
816cdcd52d4SBartosz Sobczak MODULE_DEPEND(irdma, ibcore, 1, 1, 1);
817