1e126ba97SEli Cohen /*
2302bdf68SSaeed Mahameed  * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
3e126ba97SEli Cohen  *
4e126ba97SEli Cohen  * This software is available to you under a choice of one of two
5e126ba97SEli Cohen  * licenses.  You may choose to be licensed under the terms of the GNU
6e126ba97SEli Cohen  * General Public License (GPL) Version 2, available from the file
7e126ba97SEli Cohen  * COPYING in the main directory of this source tree, or the
8e126ba97SEli Cohen  * OpenIB.org BSD license below:
9e126ba97SEli Cohen  *
10e126ba97SEli Cohen  *     Redistribution and use in source and binary forms, with or
11e126ba97SEli Cohen  *     without modification, are permitted provided that the following
12e126ba97SEli Cohen  *     conditions are met:
13e126ba97SEli Cohen  *
14e126ba97SEli Cohen  *      - Redistributions of source code must retain the above
15e126ba97SEli Cohen  *        copyright notice, this list of conditions and the following
16e126ba97SEli Cohen  *        disclaimer.
17e126ba97SEli Cohen  *
18e126ba97SEli Cohen  *      - Redistributions in binary form must reproduce the above
19e126ba97SEli Cohen  *        copyright notice, this list of conditions and the following
20e126ba97SEli Cohen  *        disclaimer in the documentation and/or other materials
21e126ba97SEli Cohen  *        provided with the distribution.
22e126ba97SEli Cohen  *
23e126ba97SEli Cohen  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e126ba97SEli Cohen  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e126ba97SEli Cohen  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e126ba97SEli Cohen  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e126ba97SEli Cohen  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e126ba97SEli Cohen  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e126ba97SEli Cohen  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e126ba97SEli Cohen  * SOFTWARE.
31e126ba97SEli Cohen  */
32e126ba97SEli Cohen 
33e126ba97SEli Cohen #include <asm-generic/kmap_types.h>
34e126ba97SEli Cohen #include <linux/module.h>
35e126ba97SEli Cohen #include <linux/init.h>
36e126ba97SEli Cohen #include <linux/errno.h>
37e126ba97SEli Cohen #include <linux/pci.h>
38e126ba97SEli Cohen #include <linux/dma-mapping.h>
39e126ba97SEli Cohen #include <linux/slab.h>
40e126ba97SEli Cohen #include <linux/io-mapping.h>
41db058a18SSaeed Mahameed #include <linux/interrupt.h>
42e126ba97SEli Cohen #include <linux/mlx5/driver.h>
43e126ba97SEli Cohen #include <linux/mlx5/cq.h>
44e126ba97SEli Cohen #include <linux/mlx5/qp.h>
45e126ba97SEli Cohen #include <linux/mlx5/srq.h>
46e126ba97SEli Cohen #include <linux/debugfs.h>
47f66f049fSEli Cohen #include <linux/kmod.h>
48b775516bSEli Cohen #include <linux/mlx5/mlx5_ifc.h>
49e126ba97SEli Cohen #include "mlx5_core.h"
50e126ba97SEli Cohen 
51e126ba97SEli Cohen MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
524ae6c18cSAchiad Shochat MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver");
53e126ba97SEli Cohen MODULE_LICENSE("Dual BSD/GPL");
54e126ba97SEli Cohen MODULE_VERSION(DRIVER_VERSION);
55e126ba97SEli Cohen 
56e126ba97SEli Cohen int mlx5_core_debug_mask;
57e126ba97SEli Cohen module_param_named(debug_mask, mlx5_core_debug_mask, int, 0644);
58e126ba97SEli Cohen MODULE_PARM_DESC(debug_mask, "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0");
59e126ba97SEli Cohen 
609603b61dSJack Morgenstein #define MLX5_DEFAULT_PROF	2
619603b61dSJack Morgenstein static int prof_sel = MLX5_DEFAULT_PROF;
629603b61dSJack Morgenstein module_param_named(prof_sel, prof_sel, int, 0444);
639603b61dSJack Morgenstein MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
649603b61dSJack Morgenstein 
65e126ba97SEli Cohen struct workqueue_struct *mlx5_core_wq;
669603b61dSJack Morgenstein static LIST_HEAD(intf_list);
679603b61dSJack Morgenstein static LIST_HEAD(dev_list);
689603b61dSJack Morgenstein static DEFINE_MUTEX(intf_mutex);
699603b61dSJack Morgenstein 
709603b61dSJack Morgenstein struct mlx5_device_context {
719603b61dSJack Morgenstein 	struct list_head	list;
729603b61dSJack Morgenstein 	struct mlx5_interface  *intf;
739603b61dSJack Morgenstein 	void		       *context;
749603b61dSJack Morgenstein };
759603b61dSJack Morgenstein 
769603b61dSJack Morgenstein static struct mlx5_profile profile[] = {
779603b61dSJack Morgenstein 	[0] = {
789603b61dSJack Morgenstein 		.mask           = 0,
799603b61dSJack Morgenstein 	},
809603b61dSJack Morgenstein 	[1] = {
819603b61dSJack Morgenstein 		.mask		= MLX5_PROF_MASK_QP_SIZE,
829603b61dSJack Morgenstein 		.log_max_qp	= 12,
839603b61dSJack Morgenstein 	},
849603b61dSJack Morgenstein 	[2] = {
859603b61dSJack Morgenstein 		.mask		= MLX5_PROF_MASK_QP_SIZE |
869603b61dSJack Morgenstein 				  MLX5_PROF_MASK_MR_CACHE,
879603b61dSJack Morgenstein 		.log_max_qp	= 17,
889603b61dSJack Morgenstein 		.mr_cache[0]	= {
899603b61dSJack Morgenstein 			.size	= 500,
909603b61dSJack Morgenstein 			.limit	= 250
919603b61dSJack Morgenstein 		},
929603b61dSJack Morgenstein 		.mr_cache[1]	= {
939603b61dSJack Morgenstein 			.size	= 500,
949603b61dSJack Morgenstein 			.limit	= 250
959603b61dSJack Morgenstein 		},
969603b61dSJack Morgenstein 		.mr_cache[2]	= {
979603b61dSJack Morgenstein 			.size	= 500,
989603b61dSJack Morgenstein 			.limit	= 250
999603b61dSJack Morgenstein 		},
1009603b61dSJack Morgenstein 		.mr_cache[3]	= {
1019603b61dSJack Morgenstein 			.size	= 500,
1029603b61dSJack Morgenstein 			.limit	= 250
1039603b61dSJack Morgenstein 		},
1049603b61dSJack Morgenstein 		.mr_cache[4]	= {
1059603b61dSJack Morgenstein 			.size	= 500,
1069603b61dSJack Morgenstein 			.limit	= 250
1079603b61dSJack Morgenstein 		},
1089603b61dSJack Morgenstein 		.mr_cache[5]	= {
1099603b61dSJack Morgenstein 			.size	= 500,
1109603b61dSJack Morgenstein 			.limit	= 250
1119603b61dSJack Morgenstein 		},
1129603b61dSJack Morgenstein 		.mr_cache[6]	= {
1139603b61dSJack Morgenstein 			.size	= 500,
1149603b61dSJack Morgenstein 			.limit	= 250
1159603b61dSJack Morgenstein 		},
1169603b61dSJack Morgenstein 		.mr_cache[7]	= {
1179603b61dSJack Morgenstein 			.size	= 500,
1189603b61dSJack Morgenstein 			.limit	= 250
1199603b61dSJack Morgenstein 		},
1209603b61dSJack Morgenstein 		.mr_cache[8]	= {
1219603b61dSJack Morgenstein 			.size	= 500,
1229603b61dSJack Morgenstein 			.limit	= 250
1239603b61dSJack Morgenstein 		},
1249603b61dSJack Morgenstein 		.mr_cache[9]	= {
1259603b61dSJack Morgenstein 			.size	= 500,
1269603b61dSJack Morgenstein 			.limit	= 250
1279603b61dSJack Morgenstein 		},
1289603b61dSJack Morgenstein 		.mr_cache[10]	= {
1299603b61dSJack Morgenstein 			.size	= 500,
1309603b61dSJack Morgenstein 			.limit	= 250
1319603b61dSJack Morgenstein 		},
1329603b61dSJack Morgenstein 		.mr_cache[11]	= {
1339603b61dSJack Morgenstein 			.size	= 500,
1349603b61dSJack Morgenstein 			.limit	= 250
1359603b61dSJack Morgenstein 		},
1369603b61dSJack Morgenstein 		.mr_cache[12]	= {
1379603b61dSJack Morgenstein 			.size	= 64,
1389603b61dSJack Morgenstein 			.limit	= 32
1399603b61dSJack Morgenstein 		},
1409603b61dSJack Morgenstein 		.mr_cache[13]	= {
1419603b61dSJack Morgenstein 			.size	= 32,
1429603b61dSJack Morgenstein 			.limit	= 16
1439603b61dSJack Morgenstein 		},
1449603b61dSJack Morgenstein 		.mr_cache[14]	= {
1459603b61dSJack Morgenstein 			.size	= 16,
1469603b61dSJack Morgenstein 			.limit	= 8
1479603b61dSJack Morgenstein 		},
1489603b61dSJack Morgenstein 		.mr_cache[15]	= {
1499603b61dSJack Morgenstein 			.size	= 8,
1509603b61dSJack Morgenstein 			.limit	= 4
1519603b61dSJack Morgenstein 		},
1529603b61dSJack Morgenstein 	},
1539603b61dSJack Morgenstein };
154e126ba97SEli Cohen 
155e126ba97SEli Cohen static int set_dma_caps(struct pci_dev *pdev)
156e126ba97SEli Cohen {
157e126ba97SEli Cohen 	int err;
158e126ba97SEli Cohen 
159e126ba97SEli Cohen 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
160e126ba97SEli Cohen 	if (err) {
1611a91de28SJoe Perches 		dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask\n");
162e126ba97SEli Cohen 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
163e126ba97SEli Cohen 		if (err) {
1641a91de28SJoe Perches 			dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting\n");
165e126ba97SEli Cohen 			return err;
166e126ba97SEli Cohen 		}
167e126ba97SEli Cohen 	}
168e126ba97SEli Cohen 
169e126ba97SEli Cohen 	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
170e126ba97SEli Cohen 	if (err) {
171e126ba97SEli Cohen 		dev_warn(&pdev->dev,
1721a91de28SJoe Perches 			 "Warning: couldn't set 64-bit consistent PCI DMA mask\n");
173e126ba97SEli Cohen 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
174e126ba97SEli Cohen 		if (err) {
175e126ba97SEli Cohen 			dev_err(&pdev->dev,
1761a91de28SJoe Perches 				"Can't set consistent PCI DMA mask, aborting\n");
177e126ba97SEli Cohen 			return err;
178e126ba97SEli Cohen 		}
179e126ba97SEli Cohen 	}
180e126ba97SEli Cohen 
181e126ba97SEli Cohen 	dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024);
182e126ba97SEli Cohen 	return err;
183e126ba97SEli Cohen }
184e126ba97SEli Cohen 
185e126ba97SEli Cohen static int request_bar(struct pci_dev *pdev)
186e126ba97SEli Cohen {
187e126ba97SEli Cohen 	int err = 0;
188e126ba97SEli Cohen 
189e126ba97SEli Cohen 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
1901a91de28SJoe Perches 		dev_err(&pdev->dev, "Missing registers BAR, aborting\n");
191e126ba97SEli Cohen 		return -ENODEV;
192e126ba97SEli Cohen 	}
193e126ba97SEli Cohen 
194e126ba97SEli Cohen 	err = pci_request_regions(pdev, DRIVER_NAME);
195e126ba97SEli Cohen 	if (err)
196e126ba97SEli Cohen 		dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n");
197e126ba97SEli Cohen 
198e126ba97SEli Cohen 	return err;
199e126ba97SEli Cohen }
200e126ba97SEli Cohen 
201e126ba97SEli Cohen static void release_bar(struct pci_dev *pdev)
202e126ba97SEli Cohen {
203e126ba97SEli Cohen 	pci_release_regions(pdev);
204e126ba97SEli Cohen }
205e126ba97SEli Cohen 
206e126ba97SEli Cohen static int mlx5_enable_msix(struct mlx5_core_dev *dev)
207e126ba97SEli Cohen {
208db058a18SSaeed Mahameed 	struct mlx5_priv *priv = &dev->priv;
209db058a18SSaeed Mahameed 	struct mlx5_eq_table *table = &priv->eq_table;
210938fe83cSSaeed Mahameed 	int num_eqs = 1 << MLX5_CAP_GEN(dev, log_max_eq);
211e126ba97SEli Cohen 	int nvec;
212e126ba97SEli Cohen 	int i;
213e126ba97SEli Cohen 
214938fe83cSSaeed Mahameed 	nvec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() +
215938fe83cSSaeed Mahameed 	       MLX5_EQ_VEC_COMP_BASE;
216e126ba97SEli Cohen 	nvec = min_t(int, nvec, num_eqs);
217e126ba97SEli Cohen 	if (nvec <= MLX5_EQ_VEC_COMP_BASE)
218e126ba97SEli Cohen 		return -ENOMEM;
219e126ba97SEli Cohen 
220db058a18SSaeed Mahameed 	priv->msix_arr = kcalloc(nvec, sizeof(*priv->msix_arr), GFP_KERNEL);
221db058a18SSaeed Mahameed 
222db058a18SSaeed Mahameed 	priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
223db058a18SSaeed Mahameed 	if (!priv->msix_arr || !priv->irq_info)
224db058a18SSaeed Mahameed 		goto err_free_msix;
225e126ba97SEli Cohen 
226e126ba97SEli Cohen 	for (i = 0; i < nvec; i++)
227db058a18SSaeed Mahameed 		priv->msix_arr[i].entry = i;
228e126ba97SEli Cohen 
229db058a18SSaeed Mahameed 	nvec = pci_enable_msix_range(dev->pdev, priv->msix_arr,
2303a9e161aSEli Cohen 				     MLX5_EQ_VEC_COMP_BASE + 1, nvec);
231f3c9407bSAlexander Gordeev 	if (nvec < 0)
232f3c9407bSAlexander Gordeev 		return nvec;
233e126ba97SEli Cohen 
234f3c9407bSAlexander Gordeev 	table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
235e126ba97SEli Cohen 
236e126ba97SEli Cohen 	return 0;
237db058a18SSaeed Mahameed 
238db058a18SSaeed Mahameed err_free_msix:
239db058a18SSaeed Mahameed 	kfree(priv->irq_info);
240db058a18SSaeed Mahameed 	kfree(priv->msix_arr);
241db058a18SSaeed Mahameed 	return -ENOMEM;
242e126ba97SEli Cohen }
243e126ba97SEli Cohen 
244e126ba97SEli Cohen static void mlx5_disable_msix(struct mlx5_core_dev *dev)
245e126ba97SEli Cohen {
246db058a18SSaeed Mahameed 	struct mlx5_priv *priv = &dev->priv;
247e126ba97SEli Cohen 
248e126ba97SEli Cohen 	pci_disable_msix(dev->pdev);
249db058a18SSaeed Mahameed 	kfree(priv->irq_info);
250db058a18SSaeed Mahameed 	kfree(priv->msix_arr);
251e126ba97SEli Cohen }
252e126ba97SEli Cohen 
253e126ba97SEli Cohen struct mlx5_reg_host_endianess {
254e126ba97SEli Cohen 	u8	he;
255e126ba97SEli Cohen 	u8      rsvd[15];
256e126ba97SEli Cohen };
257e126ba97SEli Cohen 
25887b8de49SEli Cohen 
25987b8de49SEli Cohen #define CAP_MASK(pos, size) ((u64)((1 << (size)) - 1) << (pos))
26087b8de49SEli Cohen 
26187b8de49SEli Cohen enum {
26287b8de49SEli Cohen 	MLX5_CAP_BITS_RW_MASK = CAP_MASK(MLX5_CAP_OFF_CMDIF_CSUM, 2) |
263c7a08ac7SEli Cohen 				MLX5_DEV_CAP_FLAG_DCT,
26487b8de49SEli Cohen };
26587b8de49SEli Cohen 
266c7a08ac7SEli Cohen static u16 to_fw_pkey_sz(u32 size)
267c7a08ac7SEli Cohen {
268c7a08ac7SEli Cohen 	switch (size) {
269c7a08ac7SEli Cohen 	case 128:
270c7a08ac7SEli Cohen 		return 0;
271c7a08ac7SEli Cohen 	case 256:
272c7a08ac7SEli Cohen 		return 1;
273c7a08ac7SEli Cohen 	case 512:
274c7a08ac7SEli Cohen 		return 2;
275c7a08ac7SEli Cohen 	case 1024:
276c7a08ac7SEli Cohen 		return 3;
277c7a08ac7SEli Cohen 	case 2048:
278c7a08ac7SEli Cohen 		return 4;
279c7a08ac7SEli Cohen 	case 4096:
280c7a08ac7SEli Cohen 		return 5;
281c7a08ac7SEli Cohen 	default:
282c7a08ac7SEli Cohen 		pr_warn("invalid pkey table size %d\n", size);
283c7a08ac7SEli Cohen 		return 0;
284c7a08ac7SEli Cohen 	}
285c7a08ac7SEli Cohen }
286c7a08ac7SEli Cohen 
287938fe83cSSaeed Mahameed int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type,
288938fe83cSSaeed Mahameed 		       enum mlx5_cap_mode cap_mode)
289c7a08ac7SEli Cohen {
290b775516bSEli Cohen 	u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)];
291b775516bSEli Cohen 	int out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
292938fe83cSSaeed Mahameed 	void *out, *hca_caps;
293938fe83cSSaeed Mahameed 	u16 opmod = (cap_type << 1) | (cap_mode & 0x01);
294c7a08ac7SEli Cohen 	int err;
295c7a08ac7SEli Cohen 
296b775516bSEli Cohen 	memset(in, 0, sizeof(in));
297b775516bSEli Cohen 	out = kzalloc(out_sz, GFP_KERNEL);
298c7a08ac7SEli Cohen 	if (!out)
299c7a08ac7SEli Cohen 		return -ENOMEM;
300938fe83cSSaeed Mahameed 
301b775516bSEli Cohen 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
302b775516bSEli Cohen 	MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
303b775516bSEli Cohen 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
304b775516bSEli Cohen 	if (err)
305b775516bSEli Cohen 		goto query_ex;
306c7a08ac7SEli Cohen 
307b775516bSEli Cohen 	err = mlx5_cmd_status_to_err_v2(out);
308c7a08ac7SEli Cohen 	if (err) {
309938fe83cSSaeed Mahameed 		mlx5_core_warn(dev,
310938fe83cSSaeed Mahameed 			       "QUERY_HCA_CAP : type(%x) opmode(%x) Failed(%d)\n",
311938fe83cSSaeed Mahameed 			       cap_type, cap_mode, err);
312c7a08ac7SEli Cohen 		goto query_ex;
313c7a08ac7SEli Cohen 	}
314c7a08ac7SEli Cohen 
315938fe83cSSaeed Mahameed 	hca_caps =  MLX5_ADDR_OF(query_hca_cap_out, out, capability);
316938fe83cSSaeed Mahameed 
317938fe83cSSaeed Mahameed 	switch (cap_mode) {
318938fe83cSSaeed Mahameed 	case HCA_CAP_OPMOD_GET_MAX:
319938fe83cSSaeed Mahameed 		memcpy(dev->hca_caps_max[cap_type], hca_caps,
320938fe83cSSaeed Mahameed 		       MLX5_UN_SZ_BYTES(hca_cap_union));
321938fe83cSSaeed Mahameed 		break;
322938fe83cSSaeed Mahameed 	case HCA_CAP_OPMOD_GET_CUR:
323938fe83cSSaeed Mahameed 		memcpy(dev->hca_caps_cur[cap_type], hca_caps,
324938fe83cSSaeed Mahameed 		       MLX5_UN_SZ_BYTES(hca_cap_union));
325938fe83cSSaeed Mahameed 		break;
326938fe83cSSaeed Mahameed 	default:
327938fe83cSSaeed Mahameed 		mlx5_core_warn(dev,
328938fe83cSSaeed Mahameed 			       "Tried to query dev cap type(%x) with wrong opmode(%x)\n",
329938fe83cSSaeed Mahameed 			       cap_type, cap_mode);
330938fe83cSSaeed Mahameed 		err = -EINVAL;
331938fe83cSSaeed Mahameed 		break;
332938fe83cSSaeed Mahameed 	}
333c7a08ac7SEli Cohen query_ex:
334c7a08ac7SEli Cohen 	kfree(out);
335c7a08ac7SEli Cohen 	return err;
336c7a08ac7SEli Cohen }
337c7a08ac7SEli Cohen 
338b775516bSEli Cohen static int set_caps(struct mlx5_core_dev *dev, void *in, int in_sz)
339c7a08ac7SEli Cohen {
340b775516bSEli Cohen 	u32 out[MLX5_ST_SZ_DW(set_hca_cap_out)];
341c7a08ac7SEli Cohen 	int err;
342c7a08ac7SEli Cohen 
343b775516bSEli Cohen 	memset(out, 0, sizeof(out));
344c7a08ac7SEli Cohen 
345b775516bSEli Cohen 	MLX5_SET(set_hca_cap_in, in, opcode, MLX5_CMD_OP_SET_HCA_CAP);
346b775516bSEli Cohen 	err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
347c7a08ac7SEli Cohen 	if (err)
348c7a08ac7SEli Cohen 		return err;
349c7a08ac7SEli Cohen 
350b775516bSEli Cohen 	err = mlx5_cmd_status_to_err_v2(out);
351c7a08ac7SEli Cohen 
352c7a08ac7SEli Cohen 	return err;
353c7a08ac7SEli Cohen }
35487b8de49SEli Cohen 
355e126ba97SEli Cohen static int handle_hca_cap(struct mlx5_core_dev *dev)
356e126ba97SEli Cohen {
357b775516bSEli Cohen 	void *set_ctx = NULL;
358c7a08ac7SEli Cohen 	struct mlx5_profile *prof = dev->profile;
359c7a08ac7SEli Cohen 	int err = -ENOMEM;
360b775516bSEli Cohen 	int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
361938fe83cSSaeed Mahameed 	void *set_hca_cap;
362e126ba97SEli Cohen 
363b775516bSEli Cohen 	set_ctx = kzalloc(set_sz, GFP_KERNEL);
364c7a08ac7SEli Cohen 	if (!set_ctx)
365e126ba97SEli Cohen 		goto query_ex;
366e126ba97SEli Cohen 
367938fe83cSSaeed Mahameed 	err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL, HCA_CAP_OPMOD_GET_MAX);
368e126ba97SEli Cohen 	if (err)
369e126ba97SEli Cohen 		goto query_ex;
370e126ba97SEli Cohen 
371938fe83cSSaeed Mahameed 	err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL, HCA_CAP_OPMOD_GET_CUR);
372c7a08ac7SEli Cohen 	if (err)
373e126ba97SEli Cohen 		goto query_ex;
374e126ba97SEli Cohen 
375938fe83cSSaeed Mahameed 	set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx,
376938fe83cSSaeed Mahameed 				   capability);
377938fe83cSSaeed Mahameed 	memcpy(set_hca_cap, dev->hca_caps_cur[MLX5_CAP_GENERAL],
378938fe83cSSaeed Mahameed 	       MLX5_ST_SZ_BYTES(cmd_hca_cap));
379938fe83cSSaeed Mahameed 
380938fe83cSSaeed Mahameed 	mlx5_core_dbg(dev, "Current Pkey table size %d Setting new size %d\n",
381707c4602SMajd Dibbiny 		      mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)),
382938fe83cSSaeed Mahameed 		      128);
383c7a08ac7SEli Cohen 	/* we limit the size of the pkey table to 128 entries for now */
384938fe83cSSaeed Mahameed 	MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size,
385938fe83cSSaeed Mahameed 		 to_fw_pkey_sz(128));
386e126ba97SEli Cohen 
387c7a08ac7SEli Cohen 	if (prof->mask & MLX5_PROF_MASK_QP_SIZE)
388938fe83cSSaeed Mahameed 		MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp,
389938fe83cSSaeed Mahameed 			 prof->log_max_qp);
390e126ba97SEli Cohen 
391938fe83cSSaeed Mahameed 	/* disable cmdif checksum */
392938fe83cSSaeed Mahameed 	MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0);
393c1868b82SEli Cohen 
394b775516bSEli Cohen 	err = set_caps(dev, set_ctx, set_sz);
395e126ba97SEli Cohen 
396e126ba97SEli Cohen query_ex:
397e126ba97SEli Cohen 	kfree(set_ctx);
398e126ba97SEli Cohen 	return err;
399e126ba97SEli Cohen }
400e126ba97SEli Cohen 
401e126ba97SEli Cohen static int set_hca_ctrl(struct mlx5_core_dev *dev)
402e126ba97SEli Cohen {
403e126ba97SEli Cohen 	struct mlx5_reg_host_endianess he_in;
404e126ba97SEli Cohen 	struct mlx5_reg_host_endianess he_out;
405e126ba97SEli Cohen 	int err;
406e126ba97SEli Cohen 
407e126ba97SEli Cohen 	memset(&he_in, 0, sizeof(he_in));
408e126ba97SEli Cohen 	he_in.he = MLX5_SET_HOST_ENDIANNESS;
409e126ba97SEli Cohen 	err = mlx5_core_access_reg(dev, &he_in,  sizeof(he_in),
410e126ba97SEli Cohen 					&he_out, sizeof(he_out),
411e126ba97SEli Cohen 					MLX5_REG_HOST_ENDIANNESS, 0, 1);
412e126ba97SEli Cohen 	return err;
413e126ba97SEli Cohen }
414e126ba97SEli Cohen 
415cd23b14bSEli Cohen static int mlx5_core_enable_hca(struct mlx5_core_dev *dev)
416cd23b14bSEli Cohen {
417cd23b14bSEli Cohen 	int err;
418cd23b14bSEli Cohen 	struct mlx5_enable_hca_mbox_in in;
419cd23b14bSEli Cohen 	struct mlx5_enable_hca_mbox_out out;
420cd23b14bSEli Cohen 
421cd23b14bSEli Cohen 	memset(&in, 0, sizeof(in));
422cd23b14bSEli Cohen 	memset(&out, 0, sizeof(out));
423cd23b14bSEli Cohen 	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ENABLE_HCA);
424cd23b14bSEli Cohen 	err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
425cd23b14bSEli Cohen 	if (err)
426cd23b14bSEli Cohen 		return err;
427cd23b14bSEli Cohen 
428cd23b14bSEli Cohen 	if (out.hdr.status)
429cd23b14bSEli Cohen 		return mlx5_cmd_status_to_err(&out.hdr);
430cd23b14bSEli Cohen 
431cd23b14bSEli Cohen 	return 0;
432cd23b14bSEli Cohen }
433cd23b14bSEli Cohen 
434cd23b14bSEli Cohen static int mlx5_core_disable_hca(struct mlx5_core_dev *dev)
435cd23b14bSEli Cohen {
436cd23b14bSEli Cohen 	int err;
437cd23b14bSEli Cohen 	struct mlx5_disable_hca_mbox_in in;
438cd23b14bSEli Cohen 	struct mlx5_disable_hca_mbox_out out;
439cd23b14bSEli Cohen 
440cd23b14bSEli Cohen 	memset(&in, 0, sizeof(in));
441cd23b14bSEli Cohen 	memset(&out, 0, sizeof(out));
442cd23b14bSEli Cohen 	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DISABLE_HCA);
443cd23b14bSEli Cohen 	err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
444cd23b14bSEli Cohen 	if (err)
445cd23b14bSEli Cohen 		return err;
446cd23b14bSEli Cohen 
447cd23b14bSEli Cohen 	if (out.hdr.status)
448cd23b14bSEli Cohen 		return mlx5_cmd_status_to_err(&out.hdr);
449cd23b14bSEli Cohen 
450cd23b14bSEli Cohen 	return 0;
451cd23b14bSEli Cohen }
452cd23b14bSEli Cohen 
453db058a18SSaeed Mahameed static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
454db058a18SSaeed Mahameed {
455db058a18SSaeed Mahameed 	struct mlx5_priv *priv  = &mdev->priv;
456db058a18SSaeed Mahameed 	struct msix_entry *msix = priv->msix_arr;
457db058a18SSaeed Mahameed 	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
458311c7c71SSaeed Mahameed 	int numa_node           = priv->numa_node;
459db058a18SSaeed Mahameed 	int err;
460db058a18SSaeed Mahameed 
461db058a18SSaeed Mahameed 	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
462db058a18SSaeed Mahameed 		mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
463db058a18SSaeed Mahameed 		return -ENOMEM;
464db058a18SSaeed Mahameed 	}
465db058a18SSaeed Mahameed 
466dda922c8SDavid S. Miller 	cpumask_set_cpu(cpumask_local_spread(i, numa_node),
467dda922c8SDavid S. Miller 			priv->irq_info[i].mask);
468db058a18SSaeed Mahameed 
469db058a18SSaeed Mahameed 	err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
470db058a18SSaeed Mahameed 	if (err) {
471db058a18SSaeed Mahameed 		mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x",
472db058a18SSaeed Mahameed 			       irq);
473db058a18SSaeed Mahameed 		goto err_clear_mask;
474db058a18SSaeed Mahameed 	}
475db058a18SSaeed Mahameed 
476db058a18SSaeed Mahameed 	return 0;
477db058a18SSaeed Mahameed 
478db058a18SSaeed Mahameed err_clear_mask:
479db058a18SSaeed Mahameed 	free_cpumask_var(priv->irq_info[i].mask);
480db058a18SSaeed Mahameed 	return err;
481db058a18SSaeed Mahameed }
482db058a18SSaeed Mahameed 
483db058a18SSaeed Mahameed static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
484db058a18SSaeed Mahameed {
485db058a18SSaeed Mahameed 	struct mlx5_priv *priv  = &mdev->priv;
486db058a18SSaeed Mahameed 	struct msix_entry *msix = priv->msix_arr;
487db058a18SSaeed Mahameed 	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
488db058a18SSaeed Mahameed 
489db058a18SSaeed Mahameed 	irq_set_affinity_hint(irq, NULL);
490db058a18SSaeed Mahameed 	free_cpumask_var(priv->irq_info[i].mask);
491db058a18SSaeed Mahameed }
492db058a18SSaeed Mahameed 
493db058a18SSaeed Mahameed static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
494db058a18SSaeed Mahameed {
495db058a18SSaeed Mahameed 	int err;
496db058a18SSaeed Mahameed 	int i;
497db058a18SSaeed Mahameed 
498db058a18SSaeed Mahameed 	for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++) {
499db058a18SSaeed Mahameed 		err = mlx5_irq_set_affinity_hint(mdev, i);
500db058a18SSaeed Mahameed 		if (err)
501db058a18SSaeed Mahameed 			goto err_out;
502db058a18SSaeed Mahameed 	}
503db058a18SSaeed Mahameed 
504db058a18SSaeed Mahameed 	return 0;
505db058a18SSaeed Mahameed 
506db058a18SSaeed Mahameed err_out:
507db058a18SSaeed Mahameed 	for (i--; i >= 0; i--)
508db058a18SSaeed Mahameed 		mlx5_irq_clear_affinity_hint(mdev, i);
509db058a18SSaeed Mahameed 
510db058a18SSaeed Mahameed 	return err;
511db058a18SSaeed Mahameed }
512db058a18SSaeed Mahameed 
513db058a18SSaeed Mahameed static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
514db058a18SSaeed Mahameed {
515db058a18SSaeed Mahameed 	int i;
516db058a18SSaeed Mahameed 
517db058a18SSaeed Mahameed 	for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++)
518db058a18SSaeed Mahameed 		mlx5_irq_clear_affinity_hint(mdev, i);
519db058a18SSaeed Mahameed }
520db058a18SSaeed Mahameed 
521233d05d2SSaeed Mahameed int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn)
522233d05d2SSaeed Mahameed {
523233d05d2SSaeed Mahameed 	struct mlx5_eq_table *table = &dev->priv.eq_table;
524233d05d2SSaeed Mahameed 	struct mlx5_eq *eq, *n;
525233d05d2SSaeed Mahameed 	int err = -ENOENT;
526233d05d2SSaeed Mahameed 
527233d05d2SSaeed Mahameed 	spin_lock(&table->lock);
528233d05d2SSaeed Mahameed 	list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
529233d05d2SSaeed Mahameed 		if (eq->index == vector) {
530233d05d2SSaeed Mahameed 			*eqn = eq->eqn;
531233d05d2SSaeed Mahameed 			*irqn = eq->irqn;
532233d05d2SSaeed Mahameed 			err = 0;
533233d05d2SSaeed Mahameed 			break;
534233d05d2SSaeed Mahameed 		}
535233d05d2SSaeed Mahameed 	}
536233d05d2SSaeed Mahameed 	spin_unlock(&table->lock);
537233d05d2SSaeed Mahameed 
538233d05d2SSaeed Mahameed 	return err;
539233d05d2SSaeed Mahameed }
540233d05d2SSaeed Mahameed EXPORT_SYMBOL(mlx5_vector2eqn);
541233d05d2SSaeed Mahameed 
542233d05d2SSaeed Mahameed static void free_comp_eqs(struct mlx5_core_dev *dev)
543233d05d2SSaeed Mahameed {
544233d05d2SSaeed Mahameed 	struct mlx5_eq_table *table = &dev->priv.eq_table;
545233d05d2SSaeed Mahameed 	struct mlx5_eq *eq, *n;
546233d05d2SSaeed Mahameed 
547233d05d2SSaeed Mahameed 	spin_lock(&table->lock);
548233d05d2SSaeed Mahameed 	list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
549233d05d2SSaeed Mahameed 		list_del(&eq->list);
550233d05d2SSaeed Mahameed 		spin_unlock(&table->lock);
551233d05d2SSaeed Mahameed 		if (mlx5_destroy_unmap_eq(dev, eq))
552233d05d2SSaeed Mahameed 			mlx5_core_warn(dev, "failed to destroy EQ 0x%x\n",
553233d05d2SSaeed Mahameed 				       eq->eqn);
554233d05d2SSaeed Mahameed 		kfree(eq);
555233d05d2SSaeed Mahameed 		spin_lock(&table->lock);
556233d05d2SSaeed Mahameed 	}
557233d05d2SSaeed Mahameed 	spin_unlock(&table->lock);
558233d05d2SSaeed Mahameed }
559233d05d2SSaeed Mahameed 
560233d05d2SSaeed Mahameed static int alloc_comp_eqs(struct mlx5_core_dev *dev)
561233d05d2SSaeed Mahameed {
562233d05d2SSaeed Mahameed 	struct mlx5_eq_table *table = &dev->priv.eq_table;
563db058a18SSaeed Mahameed 	char name[MLX5_MAX_IRQ_NAME];
564233d05d2SSaeed Mahameed 	struct mlx5_eq *eq;
565233d05d2SSaeed Mahameed 	int ncomp_vec;
566233d05d2SSaeed Mahameed 	int nent;
567233d05d2SSaeed Mahameed 	int err;
568233d05d2SSaeed Mahameed 	int i;
569233d05d2SSaeed Mahameed 
570233d05d2SSaeed Mahameed 	INIT_LIST_HEAD(&table->comp_eqs_list);
571233d05d2SSaeed Mahameed 	ncomp_vec = table->num_comp_vectors;
572233d05d2SSaeed Mahameed 	nent = MLX5_COMP_EQ_SIZE;
573233d05d2SSaeed Mahameed 	for (i = 0; i < ncomp_vec; i++) {
574233d05d2SSaeed Mahameed 		eq = kzalloc(sizeof(*eq), GFP_KERNEL);
575233d05d2SSaeed Mahameed 		if (!eq) {
576233d05d2SSaeed Mahameed 			err = -ENOMEM;
577233d05d2SSaeed Mahameed 			goto clean;
578233d05d2SSaeed Mahameed 		}
579233d05d2SSaeed Mahameed 
580db058a18SSaeed Mahameed 		snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
581233d05d2SSaeed Mahameed 		err = mlx5_create_map_eq(dev, eq,
582233d05d2SSaeed Mahameed 					 i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
583233d05d2SSaeed Mahameed 					 name, &dev->priv.uuari.uars[0]);
584233d05d2SSaeed Mahameed 		if (err) {
585233d05d2SSaeed Mahameed 			kfree(eq);
586233d05d2SSaeed Mahameed 			goto clean;
587233d05d2SSaeed Mahameed 		}
588233d05d2SSaeed Mahameed 		mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn);
589233d05d2SSaeed Mahameed 		eq->index = i;
590233d05d2SSaeed Mahameed 		spin_lock(&table->lock);
591233d05d2SSaeed Mahameed 		list_add_tail(&eq->list, &table->comp_eqs_list);
592233d05d2SSaeed Mahameed 		spin_unlock(&table->lock);
593233d05d2SSaeed Mahameed 	}
594233d05d2SSaeed Mahameed 
595233d05d2SSaeed Mahameed 	return 0;
596233d05d2SSaeed Mahameed 
597233d05d2SSaeed Mahameed clean:
598233d05d2SSaeed Mahameed 	free_comp_eqs(dev);
599233d05d2SSaeed Mahameed 	return err;
600233d05d2SSaeed Mahameed }
601233d05d2SSaeed Mahameed 
602f62b8bb8SAmir Vadai #ifdef CONFIG_MLX5_CORE_EN
603f62b8bb8SAmir Vadai static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
604f62b8bb8SAmir Vadai {
605f62b8bb8SAmir Vadai 	u32 query_in[MLX5_ST_SZ_DW(query_issi_in)];
606f62b8bb8SAmir Vadai 	u32 query_out[MLX5_ST_SZ_DW(query_issi_out)];
607f62b8bb8SAmir Vadai 	u32 set_in[MLX5_ST_SZ_DW(set_issi_in)];
608f62b8bb8SAmir Vadai 	u32 set_out[MLX5_ST_SZ_DW(set_issi_out)];
609f62b8bb8SAmir Vadai 	int err;
610f62b8bb8SAmir Vadai 	u32 sup_issi;
611f62b8bb8SAmir Vadai 
612f62b8bb8SAmir Vadai 	memset(query_in, 0, sizeof(query_in));
613f62b8bb8SAmir Vadai 	memset(query_out, 0, sizeof(query_out));
614f62b8bb8SAmir Vadai 
615f62b8bb8SAmir Vadai 	MLX5_SET(query_issi_in, query_in, opcode, MLX5_CMD_OP_QUERY_ISSI);
616f62b8bb8SAmir Vadai 
617f62b8bb8SAmir Vadai 	err = mlx5_cmd_exec_check_status(dev, query_in, sizeof(query_in),
618f62b8bb8SAmir Vadai 					 query_out, sizeof(query_out));
619f62b8bb8SAmir Vadai 	if (err) {
620f62b8bb8SAmir Vadai 		if (((struct mlx5_outbox_hdr *)query_out)->status ==
621f62b8bb8SAmir Vadai 		    MLX5_CMD_STAT_BAD_OP_ERR) {
622f62b8bb8SAmir Vadai 			pr_debug("Only ISSI 0 is supported\n");
623f62b8bb8SAmir Vadai 			return 0;
624f62b8bb8SAmir Vadai 		}
625f62b8bb8SAmir Vadai 
626f62b8bb8SAmir Vadai 		pr_err("failed to query ISSI\n");
627f62b8bb8SAmir Vadai 		return err;
628f62b8bb8SAmir Vadai 	}
629f62b8bb8SAmir Vadai 
630f62b8bb8SAmir Vadai 	sup_issi = MLX5_GET(query_issi_out, query_out, supported_issi_dw0);
631f62b8bb8SAmir Vadai 
632f62b8bb8SAmir Vadai 	if (sup_issi & (1 << 1)) {
633f62b8bb8SAmir Vadai 		memset(set_in, 0, sizeof(set_in));
634f62b8bb8SAmir Vadai 		memset(set_out, 0, sizeof(set_out));
635f62b8bb8SAmir Vadai 
636f62b8bb8SAmir Vadai 		MLX5_SET(set_issi_in, set_in, opcode, MLX5_CMD_OP_SET_ISSI);
637f62b8bb8SAmir Vadai 		MLX5_SET(set_issi_in, set_in, current_issi, 1);
638f62b8bb8SAmir Vadai 
639f62b8bb8SAmir Vadai 		err = mlx5_cmd_exec_check_status(dev, set_in, sizeof(set_in),
640f62b8bb8SAmir Vadai 						 set_out, sizeof(set_out));
641f62b8bb8SAmir Vadai 		if (err) {
642f62b8bb8SAmir Vadai 			pr_err("failed to set ISSI=1\n");
643f62b8bb8SAmir Vadai 			return err;
644f62b8bb8SAmir Vadai 		}
645f62b8bb8SAmir Vadai 
646f62b8bb8SAmir Vadai 		dev->issi = 1;
647f62b8bb8SAmir Vadai 
648f62b8bb8SAmir Vadai 		return 0;
649e74a1db0SHaggai Abramonvsky 	} else if (sup_issi & (1 << 0) || !sup_issi) {
650f62b8bb8SAmir Vadai 		return 0;
651f62b8bb8SAmir Vadai 	}
652f62b8bb8SAmir Vadai 
653f62b8bb8SAmir Vadai 	return -ENOTSUPP;
654f62b8bb8SAmir Vadai }
655f62b8bb8SAmir Vadai #endif
656f62b8bb8SAmir Vadai 
6579603b61dSJack Morgenstein static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
658e126ba97SEli Cohen {
659e126ba97SEli Cohen 	struct mlx5_priv *priv = &dev->priv;
660e126ba97SEli Cohen 	int err;
661e126ba97SEli Cohen 
662e126ba97SEli Cohen 	dev->pdev = pdev;
663e126ba97SEli Cohen 	pci_set_drvdata(dev->pdev, dev);
664e126ba97SEli Cohen 	strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN);
665e126ba97SEli Cohen 	priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
666e126ba97SEli Cohen 
667e126ba97SEli Cohen 	mutex_init(&priv->pgdir_mutex);
668e126ba97SEli Cohen 	INIT_LIST_HEAD(&priv->pgdir_list);
669e126ba97SEli Cohen 	spin_lock_init(&priv->mkey_lock);
670e126ba97SEli Cohen 
671311c7c71SSaeed Mahameed 	mutex_init(&priv->alloc_mutex);
672311c7c71SSaeed Mahameed 
673311c7c71SSaeed Mahameed 	priv->numa_node = dev_to_node(&dev->pdev->dev);
674311c7c71SSaeed Mahameed 
675e126ba97SEli Cohen 	priv->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), mlx5_debugfs_root);
676e126ba97SEli Cohen 	if (!priv->dbg_root)
677e126ba97SEli Cohen 		return -ENOMEM;
678e126ba97SEli Cohen 
679e126ba97SEli Cohen 	err = pci_enable_device(pdev);
680e126ba97SEli Cohen 	if (err) {
6811a91de28SJoe Perches 		dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
682e126ba97SEli Cohen 		goto err_dbg;
683e126ba97SEli Cohen 	}
684e126ba97SEli Cohen 
685e126ba97SEli Cohen 	err = request_bar(pdev);
686e126ba97SEli Cohen 	if (err) {
6871a91de28SJoe Perches 		dev_err(&pdev->dev, "error requesting BARs, aborting\n");
688e126ba97SEli Cohen 		goto err_disable;
689e126ba97SEli Cohen 	}
690e126ba97SEli Cohen 
691e126ba97SEli Cohen 	pci_set_master(pdev);
692e126ba97SEli Cohen 
693e126ba97SEli Cohen 	err = set_dma_caps(pdev);
694e126ba97SEli Cohen 	if (err) {
695e126ba97SEli Cohen 		dev_err(&pdev->dev, "Failed setting DMA capabilities mask, aborting\n");
696e126ba97SEli Cohen 		goto err_clr_master;
697e126ba97SEli Cohen 	}
698e126ba97SEli Cohen 
699e126ba97SEli Cohen 	dev->iseg_base = pci_resource_start(dev->pdev, 0);
700e126ba97SEli Cohen 	dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg));
701e126ba97SEli Cohen 	if (!dev->iseg) {
702e126ba97SEli Cohen 		err = -ENOMEM;
703e126ba97SEli Cohen 		dev_err(&pdev->dev, "Failed mapping initialization segment, aborting\n");
704e126ba97SEli Cohen 		goto err_clr_master;
705e126ba97SEli Cohen 	}
706e126ba97SEli Cohen 	dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev),
707e126ba97SEli Cohen 		 fw_rev_min(dev), fw_rev_sub(dev));
708e126ba97SEli Cohen 
709e126ba97SEli Cohen 	err = mlx5_cmd_init(dev);
710e126ba97SEli Cohen 	if (err) {
711e126ba97SEli Cohen 		dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
712e126ba97SEli Cohen 		goto err_unmap;
713e126ba97SEli Cohen 	}
714e126ba97SEli Cohen 
715e126ba97SEli Cohen 	mlx5_pagealloc_init(dev);
716cd23b14bSEli Cohen 
717cd23b14bSEli Cohen 	err = mlx5_core_enable_hca(dev);
718cd23b14bSEli Cohen 	if (err) {
719cd23b14bSEli Cohen 		dev_err(&pdev->dev, "enable hca failed\n");
720cd23b14bSEli Cohen 		goto err_pagealloc_cleanup;
721cd23b14bSEli Cohen 	}
722cd23b14bSEli Cohen 
723f62b8bb8SAmir Vadai #ifdef CONFIG_MLX5_CORE_EN
724f62b8bb8SAmir Vadai 	err = mlx5_core_set_issi(dev);
725f62b8bb8SAmir Vadai 	if (err) {
726f62b8bb8SAmir Vadai 		dev_err(&pdev->dev, "failed to set issi\n");
727f62b8bb8SAmir Vadai 		goto err_disable_hca;
728f62b8bb8SAmir Vadai 	}
729f62b8bb8SAmir Vadai #endif
730f62b8bb8SAmir Vadai 
731cd23b14bSEli Cohen 	err = mlx5_satisfy_startup_pages(dev, 1);
732cd23b14bSEli Cohen 	if (err) {
733cd23b14bSEli Cohen 		dev_err(&pdev->dev, "failed to allocate boot pages\n");
734cd23b14bSEli Cohen 		goto err_disable_hca;
735cd23b14bSEli Cohen 	}
736cd23b14bSEli Cohen 
737e126ba97SEli Cohen 	err = set_hca_ctrl(dev);
738e126ba97SEli Cohen 	if (err) {
739e126ba97SEli Cohen 		dev_err(&pdev->dev, "set_hca_ctrl failed\n");
740cd23b14bSEli Cohen 		goto reclaim_boot_pages;
741e126ba97SEli Cohen 	}
742e126ba97SEli Cohen 
743e126ba97SEli Cohen 	err = handle_hca_cap(dev);
744e126ba97SEli Cohen 	if (err) {
745e126ba97SEli Cohen 		dev_err(&pdev->dev, "handle_hca_cap failed\n");
746cd23b14bSEli Cohen 		goto reclaim_boot_pages;
747e126ba97SEli Cohen 	}
748e126ba97SEli Cohen 
749cd23b14bSEli Cohen 	err = mlx5_satisfy_startup_pages(dev, 0);
750e126ba97SEli Cohen 	if (err) {
751cd23b14bSEli Cohen 		dev_err(&pdev->dev, "failed to allocate init pages\n");
752cd23b14bSEli Cohen 		goto reclaim_boot_pages;
753e126ba97SEli Cohen 	}
754e126ba97SEli Cohen 
755e126ba97SEli Cohen 	err = mlx5_pagealloc_start(dev);
756e126ba97SEli Cohen 	if (err) {
757e126ba97SEli Cohen 		dev_err(&pdev->dev, "mlx5_pagealloc_start failed\n");
758cd23b14bSEli Cohen 		goto reclaim_boot_pages;
759e126ba97SEli Cohen 	}
760e126ba97SEli Cohen 
761e126ba97SEli Cohen 	err = mlx5_cmd_init_hca(dev);
762e126ba97SEli Cohen 	if (err) {
763e126ba97SEli Cohen 		dev_err(&pdev->dev, "init hca failed\n");
764e126ba97SEli Cohen 		goto err_pagealloc_stop;
765e126ba97SEli Cohen 	}
766e126ba97SEli Cohen 
767e126ba97SEli Cohen 	mlx5_start_health_poll(dev);
768e126ba97SEli Cohen 
769938fe83cSSaeed Mahameed 	err = mlx5_query_hca_caps(dev);
770e126ba97SEli Cohen 	if (err) {
771e126ba97SEli Cohen 		dev_err(&pdev->dev, "query hca failed\n");
772e126ba97SEli Cohen 		goto err_stop_poll;
773e126ba97SEli Cohen 	}
774e126ba97SEli Cohen 
775211e6c80SMajd Dibbiny 	err = mlx5_query_board_id(dev);
776e126ba97SEli Cohen 	if (err) {
777211e6c80SMajd Dibbiny 		dev_err(&pdev->dev, "query board id failed\n");
778e126ba97SEli Cohen 		goto err_stop_poll;
779e126ba97SEli Cohen 	}
780e126ba97SEli Cohen 
781e126ba97SEli Cohen 	err = mlx5_enable_msix(dev);
782e126ba97SEli Cohen 	if (err) {
783e126ba97SEli Cohen 		dev_err(&pdev->dev, "enable msix failed\n");
784e126ba97SEli Cohen 		goto err_stop_poll;
785e126ba97SEli Cohen 	}
786e126ba97SEli Cohen 
787e126ba97SEli Cohen 	err = mlx5_eq_init(dev);
788e126ba97SEli Cohen 	if (err) {
789e126ba97SEli Cohen 		dev_err(&pdev->dev, "failed to initialize eq\n");
790e126ba97SEli Cohen 		goto disable_msix;
791e126ba97SEli Cohen 	}
792e126ba97SEli Cohen 
793e126ba97SEli Cohen 	err = mlx5_alloc_uuars(dev, &priv->uuari);
794e126ba97SEli Cohen 	if (err) {
795e126ba97SEli Cohen 		dev_err(&pdev->dev, "Failed allocating uar, aborting\n");
796e126ba97SEli Cohen 		goto err_eq_cleanup;
797e126ba97SEli Cohen 	}
798e126ba97SEli Cohen 
799e126ba97SEli Cohen 	err = mlx5_start_eqs(dev);
800e126ba97SEli Cohen 	if (err) {
801e126ba97SEli Cohen 		dev_err(&pdev->dev, "Failed to start pages and async EQs\n");
802e126ba97SEli Cohen 		goto err_free_uar;
803e126ba97SEli Cohen 	}
804e126ba97SEli Cohen 
805233d05d2SSaeed Mahameed 	err = alloc_comp_eqs(dev);
806233d05d2SSaeed Mahameed 	if (err) {
807233d05d2SSaeed Mahameed 		dev_err(&pdev->dev, "Failed to alloc completion EQs\n");
808233d05d2SSaeed Mahameed 		goto err_stop_eqs;
809233d05d2SSaeed Mahameed 	}
810233d05d2SSaeed Mahameed 
811db058a18SSaeed Mahameed 	err = mlx5_irq_set_affinity_hints(dev);
812db058a18SSaeed Mahameed 	if (err) {
813db058a18SSaeed Mahameed 		dev_err(&pdev->dev, "Failed to alloc affinity hint cpumask\n");
814db058a18SSaeed Mahameed 		goto err_free_comp_eqs;
815db058a18SSaeed Mahameed 	}
816db058a18SSaeed Mahameed 
817e126ba97SEli Cohen 	MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock);
818e126ba97SEli Cohen 
819e126ba97SEli Cohen 	mlx5_init_cq_table(dev);
820e126ba97SEli Cohen 	mlx5_init_qp_table(dev);
821e126ba97SEli Cohen 	mlx5_init_srq_table(dev);
8223bcdb17aSSagi Grimberg 	mlx5_init_mr_table(dev);
823e126ba97SEli Cohen 
824e126ba97SEli Cohen 	return 0;
825e126ba97SEli Cohen 
826db058a18SSaeed Mahameed err_free_comp_eqs:
827db058a18SSaeed Mahameed 	free_comp_eqs(dev);
828db058a18SSaeed Mahameed 
829233d05d2SSaeed Mahameed err_stop_eqs:
830233d05d2SSaeed Mahameed 	mlx5_stop_eqs(dev);
831233d05d2SSaeed Mahameed 
832e126ba97SEli Cohen err_free_uar:
833e126ba97SEli Cohen 	mlx5_free_uuars(dev, &priv->uuari);
834e126ba97SEli Cohen 
835e126ba97SEli Cohen err_eq_cleanup:
836e126ba97SEli Cohen 	mlx5_eq_cleanup(dev);
837e126ba97SEli Cohen 
838e126ba97SEli Cohen disable_msix:
839e126ba97SEli Cohen 	mlx5_disable_msix(dev);
840e126ba97SEli Cohen 
841e126ba97SEli Cohen err_stop_poll:
842e126ba97SEli Cohen 	mlx5_stop_health_poll(dev);
8431bde6e30SEli Cohen 	if (mlx5_cmd_teardown_hca(dev)) {
8441bde6e30SEli Cohen 		dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
8451bde6e30SEli Cohen 		return err;
8461bde6e30SEli Cohen 	}
847e126ba97SEli Cohen 
848e126ba97SEli Cohen err_pagealloc_stop:
849e126ba97SEli Cohen 	mlx5_pagealloc_stop(dev);
850e126ba97SEli Cohen 
851cd23b14bSEli Cohen reclaim_boot_pages:
852e126ba97SEli Cohen 	mlx5_reclaim_startup_pages(dev);
853e126ba97SEli Cohen 
854cd23b14bSEli Cohen err_disable_hca:
855cd23b14bSEli Cohen 	mlx5_core_disable_hca(dev);
856cd23b14bSEli Cohen 
857e126ba97SEli Cohen err_pagealloc_cleanup:
858e126ba97SEli Cohen 	mlx5_pagealloc_cleanup(dev);
859e126ba97SEli Cohen 	mlx5_cmd_cleanup(dev);
860e126ba97SEli Cohen 
861e126ba97SEli Cohen err_unmap:
862e126ba97SEli Cohen 	iounmap(dev->iseg);
863e126ba97SEli Cohen 
864e126ba97SEli Cohen err_clr_master:
865e126ba97SEli Cohen 	pci_clear_master(dev->pdev);
866e126ba97SEli Cohen 	release_bar(dev->pdev);
867e126ba97SEli Cohen 
868e126ba97SEli Cohen err_disable:
869e126ba97SEli Cohen 	pci_disable_device(dev->pdev);
870e126ba97SEli Cohen 
871e126ba97SEli Cohen err_dbg:
872e126ba97SEli Cohen 	debugfs_remove(priv->dbg_root);
873e126ba97SEli Cohen 	return err;
874e126ba97SEli Cohen }
875e126ba97SEli Cohen 
8769603b61dSJack Morgenstein static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
877e126ba97SEli Cohen {
878e126ba97SEli Cohen 	struct mlx5_priv *priv = &dev->priv;
879e126ba97SEli Cohen 
880e126ba97SEli Cohen 	mlx5_cleanup_srq_table(dev);
881e126ba97SEli Cohen 	mlx5_cleanup_qp_table(dev);
882e126ba97SEli Cohen 	mlx5_cleanup_cq_table(dev);
883db058a18SSaeed Mahameed 	mlx5_irq_clear_affinity_hints(dev);
884233d05d2SSaeed Mahameed 	free_comp_eqs(dev);
885e126ba97SEli Cohen 	mlx5_stop_eqs(dev);
886e126ba97SEli Cohen 	mlx5_free_uuars(dev, &priv->uuari);
887e126ba97SEli Cohen 	mlx5_eq_cleanup(dev);
888e126ba97SEli Cohen 	mlx5_disable_msix(dev);
889e126ba97SEli Cohen 	mlx5_stop_health_poll(dev);
8901bde6e30SEli Cohen 	if (mlx5_cmd_teardown_hca(dev)) {
8911bde6e30SEli Cohen 		dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
8921bde6e30SEli Cohen 		return;
8931bde6e30SEli Cohen 	}
894e126ba97SEli Cohen 	mlx5_pagealloc_stop(dev);
895e126ba97SEli Cohen 	mlx5_reclaim_startup_pages(dev);
896cd23b14bSEli Cohen 	mlx5_core_disable_hca(dev);
897e126ba97SEli Cohen 	mlx5_pagealloc_cleanup(dev);
898e126ba97SEli Cohen 	mlx5_cmd_cleanup(dev);
899e126ba97SEli Cohen 	iounmap(dev->iseg);
900e126ba97SEli Cohen 	pci_clear_master(dev->pdev);
901e126ba97SEli Cohen 	release_bar(dev->pdev);
902e126ba97SEli Cohen 	pci_disable_device(dev->pdev);
903e126ba97SEli Cohen 	debugfs_remove(priv->dbg_root);
904e126ba97SEli Cohen }
9059603b61dSJack Morgenstein 
9069603b61dSJack Morgenstein static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
9079603b61dSJack Morgenstein {
9089603b61dSJack Morgenstein 	struct mlx5_device_context *dev_ctx;
9099603b61dSJack Morgenstein 	struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
9109603b61dSJack Morgenstein 
9119603b61dSJack Morgenstein 	dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
9129603b61dSJack Morgenstein 	if (!dev_ctx) {
9139603b61dSJack Morgenstein 		pr_warn("mlx5_add_device: alloc context failed\n");
9149603b61dSJack Morgenstein 		return;
9159603b61dSJack Morgenstein 	}
9169603b61dSJack Morgenstein 
9179603b61dSJack Morgenstein 	dev_ctx->intf    = intf;
9189603b61dSJack Morgenstein 	dev_ctx->context = intf->add(dev);
9199603b61dSJack Morgenstein 
9209603b61dSJack Morgenstein 	if (dev_ctx->context) {
9219603b61dSJack Morgenstein 		spin_lock_irq(&priv->ctx_lock);
9229603b61dSJack Morgenstein 		list_add_tail(&dev_ctx->list, &priv->ctx_list);
9239603b61dSJack Morgenstein 		spin_unlock_irq(&priv->ctx_lock);
9249603b61dSJack Morgenstein 	} else {
9259603b61dSJack Morgenstein 		kfree(dev_ctx);
9269603b61dSJack Morgenstein 	}
9279603b61dSJack Morgenstein }
9289603b61dSJack Morgenstein 
9299603b61dSJack Morgenstein static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
9309603b61dSJack Morgenstein {
9319603b61dSJack Morgenstein 	struct mlx5_device_context *dev_ctx;
9329603b61dSJack Morgenstein 	struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
9339603b61dSJack Morgenstein 
9349603b61dSJack Morgenstein 	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
9359603b61dSJack Morgenstein 		if (dev_ctx->intf == intf) {
9369603b61dSJack Morgenstein 			spin_lock_irq(&priv->ctx_lock);
9379603b61dSJack Morgenstein 			list_del(&dev_ctx->list);
9389603b61dSJack Morgenstein 			spin_unlock_irq(&priv->ctx_lock);
9399603b61dSJack Morgenstein 
9409603b61dSJack Morgenstein 			intf->remove(dev, dev_ctx->context);
9419603b61dSJack Morgenstein 			kfree(dev_ctx);
9429603b61dSJack Morgenstein 			return;
9439603b61dSJack Morgenstein 		}
9449603b61dSJack Morgenstein }
9459603b61dSJack Morgenstein static int mlx5_register_device(struct mlx5_core_dev *dev)
9469603b61dSJack Morgenstein {
9479603b61dSJack Morgenstein 	struct mlx5_priv *priv = &dev->priv;
9489603b61dSJack Morgenstein 	struct mlx5_interface *intf;
9499603b61dSJack Morgenstein 
9509603b61dSJack Morgenstein 	mutex_lock(&intf_mutex);
9519603b61dSJack Morgenstein 	list_add_tail(&priv->dev_list, &dev_list);
9529603b61dSJack Morgenstein 	list_for_each_entry(intf, &intf_list, list)
9539603b61dSJack Morgenstein 		mlx5_add_device(intf, priv);
9549603b61dSJack Morgenstein 	mutex_unlock(&intf_mutex);
9559603b61dSJack Morgenstein 
9569603b61dSJack Morgenstein 	return 0;
9579603b61dSJack Morgenstein }
9589603b61dSJack Morgenstein static void mlx5_unregister_device(struct mlx5_core_dev *dev)
9599603b61dSJack Morgenstein {
9609603b61dSJack Morgenstein 	struct mlx5_priv *priv = &dev->priv;
9619603b61dSJack Morgenstein 	struct mlx5_interface *intf;
9629603b61dSJack Morgenstein 
9639603b61dSJack Morgenstein 	mutex_lock(&intf_mutex);
9649603b61dSJack Morgenstein 	list_for_each_entry(intf, &intf_list, list)
9659603b61dSJack Morgenstein 		mlx5_remove_device(intf, priv);
9669603b61dSJack Morgenstein 	list_del(&priv->dev_list);
9679603b61dSJack Morgenstein 	mutex_unlock(&intf_mutex);
9689603b61dSJack Morgenstein }
9699603b61dSJack Morgenstein 
9709603b61dSJack Morgenstein int mlx5_register_interface(struct mlx5_interface *intf)
9719603b61dSJack Morgenstein {
9729603b61dSJack Morgenstein 	struct mlx5_priv *priv;
9739603b61dSJack Morgenstein 
9749603b61dSJack Morgenstein 	if (!intf->add || !intf->remove)
9759603b61dSJack Morgenstein 		return -EINVAL;
9769603b61dSJack Morgenstein 
9779603b61dSJack Morgenstein 	mutex_lock(&intf_mutex);
9789603b61dSJack Morgenstein 	list_add_tail(&intf->list, &intf_list);
9799603b61dSJack Morgenstein 	list_for_each_entry(priv, &dev_list, dev_list)
9809603b61dSJack Morgenstein 		mlx5_add_device(intf, priv);
9819603b61dSJack Morgenstein 	mutex_unlock(&intf_mutex);
9829603b61dSJack Morgenstein 
9839603b61dSJack Morgenstein 	return 0;
9849603b61dSJack Morgenstein }
9859603b61dSJack Morgenstein EXPORT_SYMBOL(mlx5_register_interface);
9869603b61dSJack Morgenstein 
9879603b61dSJack Morgenstein void mlx5_unregister_interface(struct mlx5_interface *intf)
9889603b61dSJack Morgenstein {
9899603b61dSJack Morgenstein 	struct mlx5_priv *priv;
9909603b61dSJack Morgenstein 
9919603b61dSJack Morgenstein 	mutex_lock(&intf_mutex);
9929603b61dSJack Morgenstein 	list_for_each_entry(priv, &dev_list, dev_list)
9939603b61dSJack Morgenstein 	       mlx5_remove_device(intf, priv);
9949603b61dSJack Morgenstein 	list_del(&intf->list);
9959603b61dSJack Morgenstein 	mutex_unlock(&intf_mutex);
9969603b61dSJack Morgenstein }
9979603b61dSJack Morgenstein EXPORT_SYMBOL(mlx5_unregister_interface);
9989603b61dSJack Morgenstein 
99964613d94SSaeed Mahameed void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
100064613d94SSaeed Mahameed {
100164613d94SSaeed Mahameed 	struct mlx5_priv *priv = &mdev->priv;
100264613d94SSaeed Mahameed 	struct mlx5_device_context *dev_ctx;
100364613d94SSaeed Mahameed 	unsigned long flags;
100464613d94SSaeed Mahameed 	void *result = NULL;
100564613d94SSaeed Mahameed 
100664613d94SSaeed Mahameed 	spin_lock_irqsave(&priv->ctx_lock, flags);
100764613d94SSaeed Mahameed 
100864613d94SSaeed Mahameed 	list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list)
100964613d94SSaeed Mahameed 		if ((dev_ctx->intf->protocol == protocol) &&
101064613d94SSaeed Mahameed 		    dev_ctx->intf->get_dev) {
101164613d94SSaeed Mahameed 			result = dev_ctx->intf->get_dev(dev_ctx->context);
101264613d94SSaeed Mahameed 			break;
101364613d94SSaeed Mahameed 		}
101464613d94SSaeed Mahameed 
101564613d94SSaeed Mahameed 	spin_unlock_irqrestore(&priv->ctx_lock, flags);
101664613d94SSaeed Mahameed 
101764613d94SSaeed Mahameed 	return result;
101864613d94SSaeed Mahameed }
101964613d94SSaeed Mahameed EXPORT_SYMBOL(mlx5_get_protocol_dev);
102064613d94SSaeed Mahameed 
10219603b61dSJack Morgenstein static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
10224d2f9bbbSJack Morgenstein 			    unsigned long param)
10239603b61dSJack Morgenstein {
10249603b61dSJack Morgenstein 	struct mlx5_priv *priv = &dev->priv;
10259603b61dSJack Morgenstein 	struct mlx5_device_context *dev_ctx;
10269603b61dSJack Morgenstein 	unsigned long flags;
10279603b61dSJack Morgenstein 
10289603b61dSJack Morgenstein 	spin_lock_irqsave(&priv->ctx_lock, flags);
10299603b61dSJack Morgenstein 
10309603b61dSJack Morgenstein 	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
10319603b61dSJack Morgenstein 		if (dev_ctx->intf->event)
10324d2f9bbbSJack Morgenstein 			dev_ctx->intf->event(dev, dev_ctx->context, event, param);
10339603b61dSJack Morgenstein 
10349603b61dSJack Morgenstein 	spin_unlock_irqrestore(&priv->ctx_lock, flags);
10359603b61dSJack Morgenstein }
10369603b61dSJack Morgenstein 
10379603b61dSJack Morgenstein struct mlx5_core_event_handler {
10389603b61dSJack Morgenstein 	void (*event)(struct mlx5_core_dev *dev,
10399603b61dSJack Morgenstein 		      enum mlx5_dev_event event,
10409603b61dSJack Morgenstein 		      void *data);
10419603b61dSJack Morgenstein };
10429603b61dSJack Morgenstein 
1043f66f049fSEli Cohen #define MLX5_IB_MOD "mlx5_ib"
1044f66f049fSEli Cohen 
10459603b61dSJack Morgenstein static int init_one(struct pci_dev *pdev,
10469603b61dSJack Morgenstein 		    const struct pci_device_id *id)
10479603b61dSJack Morgenstein {
10489603b61dSJack Morgenstein 	struct mlx5_core_dev *dev;
10499603b61dSJack Morgenstein 	struct mlx5_priv *priv;
10509603b61dSJack Morgenstein 	int err;
10519603b61dSJack Morgenstein 
10529603b61dSJack Morgenstein 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
10539603b61dSJack Morgenstein 	if (!dev) {
10549603b61dSJack Morgenstein 		dev_err(&pdev->dev, "kzalloc failed\n");
10559603b61dSJack Morgenstein 		return -ENOMEM;
10569603b61dSJack Morgenstein 	}
10579603b61dSJack Morgenstein 	priv = &dev->priv;
10589603b61dSJack Morgenstein 
10599603b61dSJack Morgenstein 	pci_set_drvdata(pdev, dev);
10609603b61dSJack Morgenstein 
10619603b61dSJack Morgenstein 	if (prof_sel < 0 || prof_sel >= ARRAY_SIZE(profile)) {
10629603b61dSJack Morgenstein 		pr_warn("selected profile out of range, selecting default (%d)\n",
10639603b61dSJack Morgenstein 			MLX5_DEFAULT_PROF);
10649603b61dSJack Morgenstein 		prof_sel = MLX5_DEFAULT_PROF;
10659603b61dSJack Morgenstein 	}
10669603b61dSJack Morgenstein 	dev->profile = &profile[prof_sel];
10679603b61dSJack Morgenstein 	dev->event = mlx5_core_event;
10689603b61dSJack Morgenstein 
1069364d1798SEli Cohen 	INIT_LIST_HEAD(&priv->ctx_list);
1070364d1798SEli Cohen 	spin_lock_init(&priv->ctx_lock);
10719603b61dSJack Morgenstein 	err = mlx5_dev_init(dev, pdev);
10729603b61dSJack Morgenstein 	if (err) {
10739603b61dSJack Morgenstein 		dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err);
10749603b61dSJack Morgenstein 		goto out;
10759603b61dSJack Morgenstein 	}
10769603b61dSJack Morgenstein 
10779603b61dSJack Morgenstein 	err = mlx5_register_device(dev);
10789603b61dSJack Morgenstein 	if (err) {
10799603b61dSJack Morgenstein 		dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
10809603b61dSJack Morgenstein 		goto out_init;
10819603b61dSJack Morgenstein 	}
10829603b61dSJack Morgenstein 
1083f66f049fSEli Cohen 	err = request_module_nowait(MLX5_IB_MOD);
1084f66f049fSEli Cohen 	if (err)
1085f66f049fSEli Cohen 		pr_info("failed request module on %s\n", MLX5_IB_MOD);
1086f66f049fSEli Cohen 
10879603b61dSJack Morgenstein 	return 0;
10889603b61dSJack Morgenstein 
10899603b61dSJack Morgenstein out_init:
10909603b61dSJack Morgenstein 	mlx5_dev_cleanup(dev);
10919603b61dSJack Morgenstein out:
10929603b61dSJack Morgenstein 	kfree(dev);
10939603b61dSJack Morgenstein 	return err;
10949603b61dSJack Morgenstein }
10959603b61dSJack Morgenstein static void remove_one(struct pci_dev *pdev)
10969603b61dSJack Morgenstein {
10979603b61dSJack Morgenstein 	struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
10989603b61dSJack Morgenstein 
10999603b61dSJack Morgenstein 	mlx5_unregister_device(dev);
11009603b61dSJack Morgenstein 	mlx5_dev_cleanup(dev);
11019603b61dSJack Morgenstein 	kfree(dev);
11029603b61dSJack Morgenstein }
11039603b61dSJack Morgenstein 
11049603b61dSJack Morgenstein static const struct pci_device_id mlx5_core_pci_table[] = {
11051c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
11061c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */
11071c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1013) }, /* ConnectX-4 */
11081c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1014) }, /* ConnectX-4 VF */
11091c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1015) }, /* ConnectX-4LX */
11101c755cc5SOr Gerlitz 	{ PCI_VDEVICE(MELLANOX, 0x1016) }, /* ConnectX-4LX VF */
11119603b61dSJack Morgenstein 	{ 0, }
11129603b61dSJack Morgenstein };
11139603b61dSJack Morgenstein 
11149603b61dSJack Morgenstein MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
11159603b61dSJack Morgenstein 
11169603b61dSJack Morgenstein static struct pci_driver mlx5_core_driver = {
11179603b61dSJack Morgenstein 	.name           = DRIVER_NAME,
11189603b61dSJack Morgenstein 	.id_table       = mlx5_core_pci_table,
11199603b61dSJack Morgenstein 	.probe          = init_one,
11209603b61dSJack Morgenstein 	.remove         = remove_one
11219603b61dSJack Morgenstein };
1122e126ba97SEli Cohen 
1123e126ba97SEli Cohen static int __init init(void)
1124e126ba97SEli Cohen {
1125e126ba97SEli Cohen 	int err;
1126e126ba97SEli Cohen 
1127e126ba97SEli Cohen 	mlx5_register_debugfs();
1128e126ba97SEli Cohen 	mlx5_core_wq = create_singlethread_workqueue("mlx5_core_wq");
1129e126ba97SEli Cohen 	if (!mlx5_core_wq) {
1130e126ba97SEli Cohen 		err = -ENOMEM;
1131e126ba97SEli Cohen 		goto err_debug;
1132e126ba97SEli Cohen 	}
1133e126ba97SEli Cohen 	mlx5_health_init();
1134e126ba97SEli Cohen 
11359603b61dSJack Morgenstein 	err = pci_register_driver(&mlx5_core_driver);
11369603b61dSJack Morgenstein 	if (err)
11379603b61dSJack Morgenstein 		goto err_health;
11389603b61dSJack Morgenstein 
1139f62b8bb8SAmir Vadai #ifdef CONFIG_MLX5_CORE_EN
1140f62b8bb8SAmir Vadai 	mlx5e_init();
1141f62b8bb8SAmir Vadai #endif
1142f62b8bb8SAmir Vadai 
1143e126ba97SEli Cohen 	return 0;
1144e126ba97SEli Cohen 
11459603b61dSJack Morgenstein err_health:
11469603b61dSJack Morgenstein 	mlx5_health_cleanup();
11479603b61dSJack Morgenstein 	destroy_workqueue(mlx5_core_wq);
1148e126ba97SEli Cohen err_debug:
1149e126ba97SEli Cohen 	mlx5_unregister_debugfs();
1150e126ba97SEli Cohen 	return err;
1151e126ba97SEli Cohen }
1152e126ba97SEli Cohen 
1153e126ba97SEli Cohen static void __exit cleanup(void)
1154e126ba97SEli Cohen {
1155f62b8bb8SAmir Vadai #ifdef CONFIG_MLX5_CORE_EN
1156f62b8bb8SAmir Vadai 	mlx5e_cleanup();
1157f62b8bb8SAmir Vadai #endif
11589603b61dSJack Morgenstein 	pci_unregister_driver(&mlx5_core_driver);
1159e126ba97SEli Cohen 	mlx5_health_cleanup();
1160e126ba97SEli Cohen 	destroy_workqueue(mlx5_core_wq);
1161e126ba97SEli Cohen 	mlx5_unregister_debugfs();
1162e126ba97SEli Cohen }
1163e126ba97SEli Cohen 
1164e126ba97SEli Cohen module_init(init);
1165e126ba97SEli Cohen module_exit(cleanup);
1166