xref: /OK3568_Linux_fs/kernel/drivers/infiniband/hw/mthca/mthca_main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3*4882a593Smuzhiyun  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
4*4882a593Smuzhiyun  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This software is available to you under a choice of one of two
7*4882a593Smuzhiyun  * licenses.  You may choose to be licensed under the terms of the GNU
8*4882a593Smuzhiyun  * General Public License (GPL) Version 2, available from the file
9*4882a593Smuzhiyun  * COPYING in the main directory of this source tree, or the
10*4882a593Smuzhiyun  * OpenIB.org BSD license below:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *     Redistribution and use in source and binary forms, with or
13*4882a593Smuzhiyun  *     without modification, are permitted provided that the following
14*4882a593Smuzhiyun  *     conditions are met:
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  *      - Redistributions of source code must retain the above
17*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
18*4882a593Smuzhiyun  *        disclaimer.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  *      - Redistributions in binary form must reproduce the above
21*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
22*4882a593Smuzhiyun  *        disclaimer in the documentation and/or other materials
23*4882a593Smuzhiyun  *        provided with the distribution.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*4882a593Smuzhiyun  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*4882a593Smuzhiyun  * SOFTWARE.
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/module.h>
36*4882a593Smuzhiyun #include <linux/init.h>
37*4882a593Smuzhiyun #include <linux/errno.h>
38*4882a593Smuzhiyun #include <linux/pci.h>
39*4882a593Smuzhiyun #include <linux/interrupt.h>
40*4882a593Smuzhiyun #include <linux/gfp.h>
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include "mthca_dev.h"
43*4882a593Smuzhiyun #include "mthca_config_reg.h"
44*4882a593Smuzhiyun #include "mthca_cmd.h"
45*4882a593Smuzhiyun #include "mthca_profile.h"
46*4882a593Smuzhiyun #include "mthca_memfree.h"
47*4882a593Smuzhiyun #include "mthca_wqe.h"
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun MODULE_AUTHOR("Roland Dreier");
50*4882a593Smuzhiyun MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
51*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun int mthca_debug_level = 0;
56*4882a593Smuzhiyun module_param_named(debug_level, mthca_debug_level, int, 0644);
57*4882a593Smuzhiyun MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #ifdef CONFIG_PCI_MSI
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static int msi_x = 1;
64*4882a593Smuzhiyun module_param(msi_x, int, 0444);
65*4882a593Smuzhiyun MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #else /* CONFIG_PCI_MSI */
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define msi_x (0)
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #endif /* CONFIG_PCI_MSI */
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static int tune_pci = 0;
74*4882a593Smuzhiyun module_param(tune_pci, int, 0444);
75*4882a593Smuzhiyun MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun DEFINE_MUTEX(mthca_device_mutex);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_QP            (1 << 16)
80*4882a593Smuzhiyun #define MTHCA_DEFAULT_RDB_PER_QP        (1 << 2)
81*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_CQ            (1 << 16)
82*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_MCG           (1 << 13)
83*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_MPT           (1 << 17)
84*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_MTT           (1 << 20)
85*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_UDAV          (1 << 15)
86*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_RESERVED_MTTS (1 << 18)
87*4882a593Smuzhiyun #define MTHCA_DEFAULT_NUM_UARC_SIZE     (1 << 18)
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static struct mthca_profile hca_profile = {
90*4882a593Smuzhiyun 	.num_qp             = MTHCA_DEFAULT_NUM_QP,
91*4882a593Smuzhiyun 	.rdb_per_qp         = MTHCA_DEFAULT_RDB_PER_QP,
92*4882a593Smuzhiyun 	.num_cq             = MTHCA_DEFAULT_NUM_CQ,
93*4882a593Smuzhiyun 	.num_mcg            = MTHCA_DEFAULT_NUM_MCG,
94*4882a593Smuzhiyun 	.num_mpt            = MTHCA_DEFAULT_NUM_MPT,
95*4882a593Smuzhiyun 	.num_mtt            = MTHCA_DEFAULT_NUM_MTT,
96*4882a593Smuzhiyun 	.num_udav           = MTHCA_DEFAULT_NUM_UDAV,          /* Tavor only */
97*4882a593Smuzhiyun 	.fmr_reserved_mtts  = MTHCA_DEFAULT_NUM_RESERVED_MTTS, /* Tavor only */
98*4882a593Smuzhiyun 	.uarc_size          = MTHCA_DEFAULT_NUM_UARC_SIZE,     /* Arbel only */
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun module_param_named(num_qp, hca_profile.num_qp, int, 0444);
102*4882a593Smuzhiyun MODULE_PARM_DESC(num_qp, "maximum number of QPs per HCA");
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun module_param_named(rdb_per_qp, hca_profile.rdb_per_qp, int, 0444);
105*4882a593Smuzhiyun MODULE_PARM_DESC(rdb_per_qp, "number of RDB buffers per QP");
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun module_param_named(num_cq, hca_profile.num_cq, int, 0444);
108*4882a593Smuzhiyun MODULE_PARM_DESC(num_cq, "maximum number of CQs per HCA");
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun module_param_named(num_mcg, hca_profile.num_mcg, int, 0444);
111*4882a593Smuzhiyun MODULE_PARM_DESC(num_mcg, "maximum number of multicast groups per HCA");
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun module_param_named(num_mpt, hca_profile.num_mpt, int, 0444);
114*4882a593Smuzhiyun MODULE_PARM_DESC(num_mpt,
115*4882a593Smuzhiyun 		"maximum number of memory protection table entries per HCA");
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun module_param_named(num_mtt, hca_profile.num_mtt, int, 0444);
118*4882a593Smuzhiyun MODULE_PARM_DESC(num_mtt,
119*4882a593Smuzhiyun 		 "maximum number of memory translation table segments per HCA");
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun module_param_named(num_udav, hca_profile.num_udav, int, 0444);
122*4882a593Smuzhiyun MODULE_PARM_DESC(num_udav, "maximum number of UD address vectors per HCA");
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun module_param_named(fmr_reserved_mtts, hca_profile.fmr_reserved_mtts, int, 0444);
125*4882a593Smuzhiyun MODULE_PARM_DESC(fmr_reserved_mtts,
126*4882a593Smuzhiyun 		 "number of memory translation table segments reserved for FMR");
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun static int log_mtts_per_seg = ilog2(MTHCA_MTT_SEG_SIZE / 8);
129*4882a593Smuzhiyun module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
130*4882a593Smuzhiyun MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static char mthca_version[] =
133*4882a593Smuzhiyun 	DRV_NAME ": Mellanox InfiniBand HCA driver v"
134*4882a593Smuzhiyun 	DRV_VERSION " (" DRV_RELDATE ")\n";
135*4882a593Smuzhiyun 
mthca_tune_pci(struct mthca_dev * mdev)136*4882a593Smuzhiyun static int mthca_tune_pci(struct mthca_dev *mdev)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun 	if (!tune_pci)
139*4882a593Smuzhiyun 		return 0;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	/* First try to max out Read Byte Count */
142*4882a593Smuzhiyun 	if (pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX)) {
143*4882a593Smuzhiyun 		if (pcix_set_mmrbc(mdev->pdev, pcix_get_max_mmrbc(mdev->pdev))) {
144*4882a593Smuzhiyun 			mthca_err(mdev, "Couldn't set PCI-X max read count, "
145*4882a593Smuzhiyun 				"aborting.\n");
146*4882a593Smuzhiyun 			return -ENODEV;
147*4882a593Smuzhiyun 		}
148*4882a593Smuzhiyun 	} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))
149*4882a593Smuzhiyun 		mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	if (pci_is_pcie(mdev->pdev)) {
152*4882a593Smuzhiyun 		if (pcie_set_readrq(mdev->pdev, 4096)) {
153*4882a593Smuzhiyun 			mthca_err(mdev, "Couldn't write PCI Express read request, "
154*4882a593Smuzhiyun 				"aborting.\n");
155*4882a593Smuzhiyun 			return -ENODEV;
156*4882a593Smuzhiyun 		}
157*4882a593Smuzhiyun 	} else if (mdev->mthca_flags & MTHCA_FLAG_PCIE)
158*4882a593Smuzhiyun 		mthca_info(mdev, "No PCI Express capability, "
159*4882a593Smuzhiyun 			   "not setting Max Read Request Size.\n");
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
mthca_dev_lim(struct mthca_dev * mdev,struct mthca_dev_lim * dev_lim)164*4882a593Smuzhiyun static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	int err;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	mdev->limits.mtt_seg_size = (1 << log_mtts_per_seg) * 8;
169*4882a593Smuzhiyun 	err = mthca_QUERY_DEV_LIM(mdev, dev_lim);
170*4882a593Smuzhiyun 	if (err) {
171*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_DEV_LIM command returned %d"
172*4882a593Smuzhiyun 				", aborting.\n", err);
173*4882a593Smuzhiyun 		return err;
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	if (dev_lim->min_page_sz > PAGE_SIZE) {
176*4882a593Smuzhiyun 		mthca_err(mdev, "HCA minimum page size of %d bigger than "
177*4882a593Smuzhiyun 			  "kernel PAGE_SIZE of %ld, aborting.\n",
178*4882a593Smuzhiyun 			  dev_lim->min_page_sz, PAGE_SIZE);
179*4882a593Smuzhiyun 		return -ENODEV;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 	if (dev_lim->num_ports > MTHCA_MAX_PORTS) {
182*4882a593Smuzhiyun 		mthca_err(mdev, "HCA has %d ports, but we only support %d, "
183*4882a593Smuzhiyun 			  "aborting.\n",
184*4882a593Smuzhiyun 			  dev_lim->num_ports, MTHCA_MAX_PORTS);
185*4882a593Smuzhiyun 		return -ENODEV;
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	if (dev_lim->uar_size > pci_resource_len(mdev->pdev, 2)) {
189*4882a593Smuzhiyun 		mthca_err(mdev, "HCA reported UAR size of 0x%x bigger than "
190*4882a593Smuzhiyun 			  "PCI resource 2 size of 0x%llx, aborting.\n",
191*4882a593Smuzhiyun 			  dev_lim->uar_size,
192*4882a593Smuzhiyun 			  (unsigned long long)pci_resource_len(mdev->pdev, 2));
193*4882a593Smuzhiyun 		return -ENODEV;
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	mdev->limits.num_ports      	= dev_lim->num_ports;
197*4882a593Smuzhiyun 	mdev->limits.vl_cap             = dev_lim->max_vl;
198*4882a593Smuzhiyun 	mdev->limits.mtu_cap            = dev_lim->max_mtu;
199*4882a593Smuzhiyun 	mdev->limits.gid_table_len  	= dev_lim->max_gids;
200*4882a593Smuzhiyun 	mdev->limits.pkey_table_len 	= dev_lim->max_pkeys;
201*4882a593Smuzhiyun 	mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
202*4882a593Smuzhiyun 	/*
203*4882a593Smuzhiyun 	 * Need to allow for worst case send WQE overhead and check
204*4882a593Smuzhiyun 	 * whether max_desc_sz imposes a lower limit than max_sg; UD
205*4882a593Smuzhiyun 	 * send has the biggest overhead.
206*4882a593Smuzhiyun 	 */
207*4882a593Smuzhiyun 	mdev->limits.max_sg		= min_t(int, dev_lim->max_sg,
208*4882a593Smuzhiyun 					      (dev_lim->max_desc_sz -
209*4882a593Smuzhiyun 					       sizeof (struct mthca_next_seg) -
210*4882a593Smuzhiyun 					       (mthca_is_memfree(mdev) ?
211*4882a593Smuzhiyun 						sizeof (struct mthca_arbel_ud_seg) :
212*4882a593Smuzhiyun 						sizeof (struct mthca_tavor_ud_seg))) /
213*4882a593Smuzhiyun 						sizeof (struct mthca_data_seg));
214*4882a593Smuzhiyun 	mdev->limits.max_wqes           = dev_lim->max_qp_sz;
215*4882a593Smuzhiyun 	mdev->limits.max_qp_init_rdma   = dev_lim->max_requester_per_qp;
216*4882a593Smuzhiyun 	mdev->limits.reserved_qps       = dev_lim->reserved_qps;
217*4882a593Smuzhiyun 	mdev->limits.max_srq_wqes       = dev_lim->max_srq_sz;
218*4882a593Smuzhiyun 	mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;
219*4882a593Smuzhiyun 	mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;
220*4882a593Smuzhiyun 	mdev->limits.max_desc_sz        = dev_lim->max_desc_sz;
221*4882a593Smuzhiyun 	mdev->limits.max_srq_sge	= mthca_max_srq_sge(mdev);
222*4882a593Smuzhiyun 	/*
223*4882a593Smuzhiyun 	 * Subtract 1 from the limit because we need to allocate a
224*4882a593Smuzhiyun 	 * spare CQE so the HCA HW can tell the difference between an
225*4882a593Smuzhiyun 	 * empty CQ and a full CQ.
226*4882a593Smuzhiyun 	 */
227*4882a593Smuzhiyun 	mdev->limits.max_cqes           = dev_lim->max_cq_sz - 1;
228*4882a593Smuzhiyun 	mdev->limits.reserved_cqs       = dev_lim->reserved_cqs;
229*4882a593Smuzhiyun 	mdev->limits.reserved_eqs       = dev_lim->reserved_eqs;
230*4882a593Smuzhiyun 	mdev->limits.reserved_mtts      = dev_lim->reserved_mtts;
231*4882a593Smuzhiyun 	mdev->limits.reserved_mrws      = dev_lim->reserved_mrws;
232*4882a593Smuzhiyun 	mdev->limits.reserved_uars      = dev_lim->reserved_uars;
233*4882a593Smuzhiyun 	mdev->limits.reserved_pds       = dev_lim->reserved_pds;
234*4882a593Smuzhiyun 	mdev->limits.port_width_cap     = dev_lim->max_port_width;
235*4882a593Smuzhiyun 	mdev->limits.page_size_cap      = ~(u32) (dev_lim->min_page_sz - 1);
236*4882a593Smuzhiyun 	mdev->limits.flags              = dev_lim->flags;
237*4882a593Smuzhiyun 	/*
238*4882a593Smuzhiyun 	 * For old FW that doesn't return static rate support, use a
239*4882a593Smuzhiyun 	 * value of 0x3 (only static rate values of 0 or 1 are handled),
240*4882a593Smuzhiyun 	 * except on Sinai, where even old FW can handle static rate
241*4882a593Smuzhiyun 	 * values of 2 and 3.
242*4882a593Smuzhiyun 	 */
243*4882a593Smuzhiyun 	if (dev_lim->stat_rate_support)
244*4882a593Smuzhiyun 		mdev->limits.stat_rate_support = dev_lim->stat_rate_support;
245*4882a593Smuzhiyun 	else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
246*4882a593Smuzhiyun 		mdev->limits.stat_rate_support = 0xf;
247*4882a593Smuzhiyun 	else
248*4882a593Smuzhiyun 		mdev->limits.stat_rate_support = 0x3;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
251*4882a593Smuzhiyun 	   May be doable since hardware supports it for SRQ.
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	   IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver.
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	   IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not
256*4882a593Smuzhiyun 	   supported by driver. */
257*4882a593Smuzhiyun 	mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
258*4882a593Smuzhiyun 		IB_DEVICE_PORT_ACTIVE_EVENT |
259*4882a593Smuzhiyun 		IB_DEVICE_SYS_IMAGE_GUID |
260*4882a593Smuzhiyun 		IB_DEVICE_RC_RNR_NAK_GEN;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR)
263*4882a593Smuzhiyun 		mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR)
266*4882a593Smuzhiyun 		mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI)
269*4882a593Smuzhiyun 		mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG)
272*4882a593Smuzhiyun 		mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE)
275*4882a593Smuzhiyun 		mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	if (dev_lim->flags & DEV_LIM_FLAG_SRQ)
278*4882a593Smuzhiyun 		mdev->mthca_flags |= MTHCA_FLAG_SRQ;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (mthca_is_memfree(mdev))
281*4882a593Smuzhiyun 		if (dev_lim->flags & DEV_LIM_FLAG_IPOIB_CSUM)
282*4882a593Smuzhiyun 			mdev->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	return 0;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
mthca_init_tavor(struct mthca_dev * mdev)287*4882a593Smuzhiyun static int mthca_init_tavor(struct mthca_dev *mdev)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	s64 size;
290*4882a593Smuzhiyun 	int err;
291*4882a593Smuzhiyun 	struct mthca_dev_lim        dev_lim;
292*4882a593Smuzhiyun 	struct mthca_profile        profile;
293*4882a593Smuzhiyun 	struct mthca_init_hca_param init_hca;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	err = mthca_SYS_EN(mdev);
296*4882a593Smuzhiyun 	if (err) {
297*4882a593Smuzhiyun 		mthca_err(mdev, "SYS_EN command returned %d, aborting.\n", err);
298*4882a593Smuzhiyun 		return err;
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	err = mthca_QUERY_FW(mdev);
302*4882a593Smuzhiyun 	if (err) {
303*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_FW command returned %d,"
304*4882a593Smuzhiyun 				" aborting.\n", err);
305*4882a593Smuzhiyun 		goto err_disable;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 	err = mthca_QUERY_DDR(mdev);
308*4882a593Smuzhiyun 	if (err) {
309*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_DDR command returned %d, aborting.\n", err);
310*4882a593Smuzhiyun 		goto err_disable;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	err = mthca_dev_lim(mdev, &dev_lim);
314*4882a593Smuzhiyun 	if (err) {
315*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_DEV_LIM command returned %d, aborting.\n", err);
316*4882a593Smuzhiyun 		goto err_disable;
317*4882a593Smuzhiyun 	}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	profile = hca_profile;
320*4882a593Smuzhiyun 	profile.num_uar   = dev_lim.uar_size / PAGE_SIZE;
321*4882a593Smuzhiyun 	profile.uarc_size = 0;
322*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
323*4882a593Smuzhiyun 		profile.num_srq = dev_lim.max_srqs;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
326*4882a593Smuzhiyun 	if (size < 0) {
327*4882a593Smuzhiyun 		err = size;
328*4882a593Smuzhiyun 		goto err_disable;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	err = mthca_INIT_HCA(mdev, &init_hca);
332*4882a593Smuzhiyun 	if (err) {
333*4882a593Smuzhiyun 		mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
334*4882a593Smuzhiyun 		goto err_disable;
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	return 0;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun err_disable:
340*4882a593Smuzhiyun 	mthca_SYS_DIS(mdev);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	return err;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun 
mthca_load_fw(struct mthca_dev * mdev)345*4882a593Smuzhiyun static int mthca_load_fw(struct mthca_dev *mdev)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	int err;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	/* FIXME: use HCA-attached memory for FW if present */
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	mdev->fw.arbel.fw_icm =
352*4882a593Smuzhiyun 		mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages,
353*4882a593Smuzhiyun 				GFP_HIGHUSER | __GFP_NOWARN, 0);
354*4882a593Smuzhiyun 	if (!mdev->fw.arbel.fw_icm) {
355*4882a593Smuzhiyun 		mthca_err(mdev, "Couldn't allocate FW area, aborting.\n");
356*4882a593Smuzhiyun 		return -ENOMEM;
357*4882a593Smuzhiyun 	}
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm);
360*4882a593Smuzhiyun 	if (err) {
361*4882a593Smuzhiyun 		mthca_err(mdev, "MAP_FA command returned %d, aborting.\n", err);
362*4882a593Smuzhiyun 		goto err_free;
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun 	err = mthca_RUN_FW(mdev);
365*4882a593Smuzhiyun 	if (err) {
366*4882a593Smuzhiyun 		mthca_err(mdev, "RUN_FW command returned %d, aborting.\n", err);
367*4882a593Smuzhiyun 		goto err_unmap_fa;
368*4882a593Smuzhiyun 	}
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	return 0;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun err_unmap_fa:
373*4882a593Smuzhiyun 	mthca_UNMAP_FA(mdev);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun err_free:
376*4882a593Smuzhiyun 	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
377*4882a593Smuzhiyun 	return err;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
mthca_init_icm(struct mthca_dev * mdev,struct mthca_dev_lim * dev_lim,struct mthca_init_hca_param * init_hca,u64 icm_size)380*4882a593Smuzhiyun static int mthca_init_icm(struct mthca_dev *mdev,
381*4882a593Smuzhiyun 			  struct mthca_dev_lim *dev_lim,
382*4882a593Smuzhiyun 			  struct mthca_init_hca_param *init_hca,
383*4882a593Smuzhiyun 			  u64 icm_size)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	u64 aux_pages;
386*4882a593Smuzhiyun 	int err;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
389*4882a593Smuzhiyun 	if (err) {
390*4882a593Smuzhiyun 		mthca_err(mdev, "SET_ICM_SIZE command returned %d, aborting.\n", err);
391*4882a593Smuzhiyun 		return err;
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n",
395*4882a593Smuzhiyun 		  (unsigned long long) icm_size >> 10,
396*4882a593Smuzhiyun 		  (unsigned long long) aux_pages << 2);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, aux_pages,
399*4882a593Smuzhiyun 						 GFP_HIGHUSER | __GFP_NOWARN, 0);
400*4882a593Smuzhiyun 	if (!mdev->fw.arbel.aux_icm) {
401*4882a593Smuzhiyun 		mthca_err(mdev, "Couldn't allocate aux memory, aborting.\n");
402*4882a593Smuzhiyun 		return -ENOMEM;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm);
406*4882a593Smuzhiyun 	if (err) {
407*4882a593Smuzhiyun 		mthca_err(mdev, "MAP_ICM_AUX returned %d, aborting.\n", err);
408*4882a593Smuzhiyun 		goto err_free_aux;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	err = mthca_map_eq_icm(mdev, init_hca->eqc_base);
412*4882a593Smuzhiyun 	if (err) {
413*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map EQ context memory, aborting.\n");
414*4882a593Smuzhiyun 		goto err_unmap_aux;
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	/* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */
418*4882a593Smuzhiyun 	mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * mdev->limits.mtt_seg_size,
419*4882a593Smuzhiyun 					   dma_get_cache_alignment()) / mdev->limits.mtt_seg_size;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
422*4882a593Smuzhiyun 							 mdev->limits.mtt_seg_size,
423*4882a593Smuzhiyun 							 mdev->limits.num_mtt_segs,
424*4882a593Smuzhiyun 							 mdev->limits.reserved_mtts,
425*4882a593Smuzhiyun 							 1, 0);
426*4882a593Smuzhiyun 	if (!mdev->mr_table.mtt_table) {
427*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map MTT context memory, aborting.\n");
428*4882a593Smuzhiyun 		err = -ENOMEM;
429*4882a593Smuzhiyun 		goto err_unmap_eq;
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,
433*4882a593Smuzhiyun 							 dev_lim->mpt_entry_sz,
434*4882a593Smuzhiyun 							 mdev->limits.num_mpts,
435*4882a593Smuzhiyun 							 mdev->limits.reserved_mrws,
436*4882a593Smuzhiyun 							 1, 1);
437*4882a593Smuzhiyun 	if (!mdev->mr_table.mpt_table) {
438*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");
439*4882a593Smuzhiyun 		err = -ENOMEM;
440*4882a593Smuzhiyun 		goto err_unmap_mtt;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,
444*4882a593Smuzhiyun 							dev_lim->qpc_entry_sz,
445*4882a593Smuzhiyun 							mdev->limits.num_qps,
446*4882a593Smuzhiyun 							mdev->limits.reserved_qps,
447*4882a593Smuzhiyun 							0, 0);
448*4882a593Smuzhiyun 	if (!mdev->qp_table.qp_table) {
449*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map QP context memory, aborting.\n");
450*4882a593Smuzhiyun 		err = -ENOMEM;
451*4882a593Smuzhiyun 		goto err_unmap_mpt;
452*4882a593Smuzhiyun 	}
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,
455*4882a593Smuzhiyun 							 dev_lim->eqpc_entry_sz,
456*4882a593Smuzhiyun 							 mdev->limits.num_qps,
457*4882a593Smuzhiyun 							 mdev->limits.reserved_qps,
458*4882a593Smuzhiyun 							 0, 0);
459*4882a593Smuzhiyun 	if (!mdev->qp_table.eqp_table) {
460*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map EQP context memory, aborting.\n");
461*4882a593Smuzhiyun 		err = -ENOMEM;
462*4882a593Smuzhiyun 		goto err_unmap_qp;
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	mdev->qp_table.rdb_table = mthca_alloc_icm_table(mdev, init_hca->rdb_base,
466*4882a593Smuzhiyun 							 MTHCA_RDB_ENTRY_SIZE,
467*4882a593Smuzhiyun 							 mdev->limits.num_qps <<
468*4882a593Smuzhiyun 							 mdev->qp_table.rdb_shift, 0,
469*4882a593Smuzhiyun 							 0, 0);
470*4882a593Smuzhiyun 	if (!mdev->qp_table.rdb_table) {
471*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map RDB context memory, aborting\n");
472*4882a593Smuzhiyun 		err = -ENOMEM;
473*4882a593Smuzhiyun 		goto err_unmap_eqp;
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
477*4882a593Smuzhiyun 						     dev_lim->cqc_entry_sz,
478*4882a593Smuzhiyun 						     mdev->limits.num_cqs,
479*4882a593Smuzhiyun 						     mdev->limits.reserved_cqs,
480*4882a593Smuzhiyun 						     0, 0);
481*4882a593Smuzhiyun 	if (!mdev->cq_table.table) {
482*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
483*4882a593Smuzhiyun 		err = -ENOMEM;
484*4882a593Smuzhiyun 		goto err_unmap_rdb;
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ) {
488*4882a593Smuzhiyun 		mdev->srq_table.table =
489*4882a593Smuzhiyun 			mthca_alloc_icm_table(mdev, init_hca->srqc_base,
490*4882a593Smuzhiyun 					      dev_lim->srq_entry_sz,
491*4882a593Smuzhiyun 					      mdev->limits.num_srqs,
492*4882a593Smuzhiyun 					      mdev->limits.reserved_srqs,
493*4882a593Smuzhiyun 					      0, 0);
494*4882a593Smuzhiyun 		if (!mdev->srq_table.table) {
495*4882a593Smuzhiyun 			mthca_err(mdev, "Failed to map SRQ context memory, "
496*4882a593Smuzhiyun 				  "aborting.\n");
497*4882a593Smuzhiyun 			err = -ENOMEM;
498*4882a593Smuzhiyun 			goto err_unmap_cq;
499*4882a593Smuzhiyun 		}
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	/*
503*4882a593Smuzhiyun 	 * It's not strictly required, but for simplicity just map the
504*4882a593Smuzhiyun 	 * whole multicast group table now.  The table isn't very big
505*4882a593Smuzhiyun 	 * and it's a lot easier than trying to track ref counts.
506*4882a593Smuzhiyun 	 */
507*4882a593Smuzhiyun 	mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base,
508*4882a593Smuzhiyun 						      MTHCA_MGM_ENTRY_SIZE,
509*4882a593Smuzhiyun 						      mdev->limits.num_mgms +
510*4882a593Smuzhiyun 						      mdev->limits.num_amgms,
511*4882a593Smuzhiyun 						      mdev->limits.num_mgms +
512*4882a593Smuzhiyun 						      mdev->limits.num_amgms,
513*4882a593Smuzhiyun 						      0, 0);
514*4882a593Smuzhiyun 	if (!mdev->mcg_table.table) {
515*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
516*4882a593Smuzhiyun 		err = -ENOMEM;
517*4882a593Smuzhiyun 		goto err_unmap_srq;
518*4882a593Smuzhiyun 	}
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	return 0;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun err_unmap_srq:
523*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
524*4882a593Smuzhiyun 		mthca_free_icm_table(mdev, mdev->srq_table.table);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun err_unmap_cq:
527*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->cq_table.table);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun err_unmap_rdb:
530*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun err_unmap_eqp:
533*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun err_unmap_qp:
536*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun err_unmap_mpt:
539*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun err_unmap_mtt:
542*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun err_unmap_eq:
545*4882a593Smuzhiyun 	mthca_unmap_eq_icm(mdev);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun err_unmap_aux:
548*4882a593Smuzhiyun 	mthca_UNMAP_ICM_AUX(mdev);
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun err_free_aux:
551*4882a593Smuzhiyun 	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	return err;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
mthca_free_icms(struct mthca_dev * mdev)556*4882a593Smuzhiyun static void mthca_free_icms(struct mthca_dev *mdev)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->mcg_table.table);
560*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
561*4882a593Smuzhiyun 		mthca_free_icm_table(mdev, mdev->srq_table.table);
562*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->cq_table.table);
563*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
564*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
565*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
566*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
567*4882a593Smuzhiyun 	mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
568*4882a593Smuzhiyun 	mthca_unmap_eq_icm(mdev);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	mthca_UNMAP_ICM_AUX(mdev);
571*4882a593Smuzhiyun 	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
mthca_init_arbel(struct mthca_dev * mdev)574*4882a593Smuzhiyun static int mthca_init_arbel(struct mthca_dev *mdev)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun 	struct mthca_dev_lim        dev_lim;
577*4882a593Smuzhiyun 	struct mthca_profile        profile;
578*4882a593Smuzhiyun 	struct mthca_init_hca_param init_hca;
579*4882a593Smuzhiyun 	s64 icm_size;
580*4882a593Smuzhiyun 	int err;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	err = mthca_QUERY_FW(mdev);
583*4882a593Smuzhiyun 	if (err) {
584*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_FW command failed %d, aborting.\n", err);
585*4882a593Smuzhiyun 		return err;
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	err = mthca_ENABLE_LAM(mdev);
589*4882a593Smuzhiyun 	if (err == -EAGAIN) {
590*4882a593Smuzhiyun 		mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n");
591*4882a593Smuzhiyun 		mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;
592*4882a593Smuzhiyun 	} else if (err) {
593*4882a593Smuzhiyun 		mthca_err(mdev, "ENABLE_LAM returned %d, aborting.\n", err);
594*4882a593Smuzhiyun 		return err;
595*4882a593Smuzhiyun 	}
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	err = mthca_load_fw(mdev);
598*4882a593Smuzhiyun 	if (err) {
599*4882a593Smuzhiyun 		mthca_err(mdev, "Loading FW returned %d, aborting.\n", err);
600*4882a593Smuzhiyun 		goto err_disable;
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	err = mthca_dev_lim(mdev, &dev_lim);
604*4882a593Smuzhiyun 	if (err) {
605*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_DEV_LIM returned %d, aborting.\n", err);
606*4882a593Smuzhiyun 		goto err_stop_fw;
607*4882a593Smuzhiyun 	}
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	profile = hca_profile;
610*4882a593Smuzhiyun 	profile.num_uar  = dev_lim.uar_size / PAGE_SIZE;
611*4882a593Smuzhiyun 	profile.num_udav = 0;
612*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
613*4882a593Smuzhiyun 		profile.num_srq = dev_lim.max_srqs;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
616*4882a593Smuzhiyun 	if (icm_size < 0) {
617*4882a593Smuzhiyun 		err = icm_size;
618*4882a593Smuzhiyun 		goto err_stop_fw;
619*4882a593Smuzhiyun 	}
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	err = mthca_init_icm(mdev, &dev_lim, &init_hca, icm_size);
622*4882a593Smuzhiyun 	if (err)
623*4882a593Smuzhiyun 		goto err_stop_fw;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	err = mthca_INIT_HCA(mdev, &init_hca);
626*4882a593Smuzhiyun 	if (err) {
627*4882a593Smuzhiyun 		mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
628*4882a593Smuzhiyun 		goto err_free_icm;
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	return 0;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun err_free_icm:
634*4882a593Smuzhiyun 	mthca_free_icms(mdev);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun err_stop_fw:
637*4882a593Smuzhiyun 	mthca_UNMAP_FA(mdev);
638*4882a593Smuzhiyun 	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun err_disable:
641*4882a593Smuzhiyun 	if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
642*4882a593Smuzhiyun 		mthca_DISABLE_LAM(mdev);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	return err;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun 
mthca_close_hca(struct mthca_dev * mdev)647*4882a593Smuzhiyun static void mthca_close_hca(struct mthca_dev *mdev)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun 	mthca_CLOSE_HCA(mdev, 0);
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	if (mthca_is_memfree(mdev)) {
652*4882a593Smuzhiyun 		mthca_free_icms(mdev);
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 		mthca_UNMAP_FA(mdev);
655*4882a593Smuzhiyun 		mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 		if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
658*4882a593Smuzhiyun 			mthca_DISABLE_LAM(mdev);
659*4882a593Smuzhiyun 	} else
660*4882a593Smuzhiyun 		mthca_SYS_DIS(mdev);
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun 
mthca_init_hca(struct mthca_dev * mdev)663*4882a593Smuzhiyun static int mthca_init_hca(struct mthca_dev *mdev)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun 	int err;
666*4882a593Smuzhiyun 	struct mthca_adapter adapter;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	if (mthca_is_memfree(mdev))
669*4882a593Smuzhiyun 		err = mthca_init_arbel(mdev);
670*4882a593Smuzhiyun 	else
671*4882a593Smuzhiyun 		err = mthca_init_tavor(mdev);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	if (err)
674*4882a593Smuzhiyun 		return err;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	err = mthca_QUERY_ADAPTER(mdev, &adapter);
677*4882a593Smuzhiyun 	if (err) {
678*4882a593Smuzhiyun 		mthca_err(mdev, "QUERY_ADAPTER command returned %d, aborting.\n", err);
679*4882a593Smuzhiyun 		goto err_close;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	mdev->eq_table.inta_pin = adapter.inta_pin;
683*4882a593Smuzhiyun 	if (!mthca_is_memfree(mdev))
684*4882a593Smuzhiyun 		mdev->rev_id = adapter.revision_id;
685*4882a593Smuzhiyun 	memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	return 0;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun err_close:
690*4882a593Smuzhiyun 	mthca_close_hca(mdev);
691*4882a593Smuzhiyun 	return err;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun 
mthca_setup_hca(struct mthca_dev * dev)694*4882a593Smuzhiyun static int mthca_setup_hca(struct mthca_dev *dev)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	int err;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	err = mthca_init_uar_table(dev);
701*4882a593Smuzhiyun 	if (err) {
702*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
703*4882a593Smuzhiyun 			  "user access region table, aborting.\n");
704*4882a593Smuzhiyun 		return err;
705*4882a593Smuzhiyun 	}
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	err = mthca_uar_alloc(dev, &dev->driver_uar);
708*4882a593Smuzhiyun 	if (err) {
709*4882a593Smuzhiyun 		mthca_err(dev, "Failed to allocate driver access region, "
710*4882a593Smuzhiyun 			  "aborting.\n");
711*4882a593Smuzhiyun 		goto err_uar_table_free;
712*4882a593Smuzhiyun 	}
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	dev->kar = ioremap((phys_addr_t) dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
715*4882a593Smuzhiyun 	if (!dev->kar) {
716*4882a593Smuzhiyun 		mthca_err(dev, "Couldn't map kernel access region, "
717*4882a593Smuzhiyun 			  "aborting.\n");
718*4882a593Smuzhiyun 		err = -ENOMEM;
719*4882a593Smuzhiyun 		goto err_uar_free;
720*4882a593Smuzhiyun 	}
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	err = mthca_init_pd_table(dev);
723*4882a593Smuzhiyun 	if (err) {
724*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
725*4882a593Smuzhiyun 			  "protection domain table, aborting.\n");
726*4882a593Smuzhiyun 		goto err_kar_unmap;
727*4882a593Smuzhiyun 	}
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	err = mthca_init_mr_table(dev);
730*4882a593Smuzhiyun 	if (err) {
731*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
732*4882a593Smuzhiyun 			  "memory region table, aborting.\n");
733*4882a593Smuzhiyun 		goto err_pd_table_free;
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	err = mthca_pd_alloc(dev, 1, &dev->driver_pd);
737*4882a593Smuzhiyun 	if (err) {
738*4882a593Smuzhiyun 		mthca_err(dev, "Failed to create driver PD, "
739*4882a593Smuzhiyun 			  "aborting.\n");
740*4882a593Smuzhiyun 		goto err_mr_table_free;
741*4882a593Smuzhiyun 	}
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	err = mthca_init_eq_table(dev);
744*4882a593Smuzhiyun 	if (err) {
745*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
746*4882a593Smuzhiyun 			  "event queue table, aborting.\n");
747*4882a593Smuzhiyun 		goto err_pd_free;
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	err = mthca_cmd_use_events(dev);
751*4882a593Smuzhiyun 	if (err) {
752*4882a593Smuzhiyun 		mthca_err(dev, "Failed to switch to event-driven "
753*4882a593Smuzhiyun 			  "firmware commands, aborting.\n");
754*4882a593Smuzhiyun 		goto err_eq_table_free;
755*4882a593Smuzhiyun 	}
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	err = mthca_NOP(dev);
758*4882a593Smuzhiyun 	if (err) {
759*4882a593Smuzhiyun 		if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
760*4882a593Smuzhiyun 			mthca_warn(dev, "NOP command failed to generate interrupt "
761*4882a593Smuzhiyun 				   "(IRQ %d).\n",
762*4882a593Smuzhiyun 				   dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector);
763*4882a593Smuzhiyun 			mthca_warn(dev, "Trying again with MSI-X disabled.\n");
764*4882a593Smuzhiyun 		} else {
765*4882a593Smuzhiyun 			mthca_err(dev, "NOP command failed to generate interrupt "
766*4882a593Smuzhiyun 				  "(IRQ %d), aborting.\n",
767*4882a593Smuzhiyun 				  dev->pdev->irq);
768*4882a593Smuzhiyun 			mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n");
769*4882a593Smuzhiyun 		}
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 		goto err_cmd_poll;
772*4882a593Smuzhiyun 	}
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	mthca_dbg(dev, "NOP command IRQ test passed\n");
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	err = mthca_init_cq_table(dev);
777*4882a593Smuzhiyun 	if (err) {
778*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
779*4882a593Smuzhiyun 			  "completion queue table, aborting.\n");
780*4882a593Smuzhiyun 		goto err_cmd_poll;
781*4882a593Smuzhiyun 	}
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	err = mthca_init_srq_table(dev);
784*4882a593Smuzhiyun 	if (err) {
785*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
786*4882a593Smuzhiyun 			  "shared receive queue table, aborting.\n");
787*4882a593Smuzhiyun 		goto err_cq_table_free;
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	err = mthca_init_qp_table(dev);
791*4882a593Smuzhiyun 	if (err) {
792*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
793*4882a593Smuzhiyun 			  "queue pair table, aborting.\n");
794*4882a593Smuzhiyun 		goto err_srq_table_free;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	err = mthca_init_av_table(dev);
798*4882a593Smuzhiyun 	if (err) {
799*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
800*4882a593Smuzhiyun 			  "address vector table, aborting.\n");
801*4882a593Smuzhiyun 		goto err_qp_table_free;
802*4882a593Smuzhiyun 	}
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	err = mthca_init_mcg_table(dev);
805*4882a593Smuzhiyun 	if (err) {
806*4882a593Smuzhiyun 		mthca_err(dev, "Failed to initialize "
807*4882a593Smuzhiyun 			  "multicast group table, aborting.\n");
808*4882a593Smuzhiyun 		goto err_av_table_free;
809*4882a593Smuzhiyun 	}
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	return 0;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun err_av_table_free:
814*4882a593Smuzhiyun 	mthca_cleanup_av_table(dev);
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun err_qp_table_free:
817*4882a593Smuzhiyun 	mthca_cleanup_qp_table(dev);
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun err_srq_table_free:
820*4882a593Smuzhiyun 	mthca_cleanup_srq_table(dev);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun err_cq_table_free:
823*4882a593Smuzhiyun 	mthca_cleanup_cq_table(dev);
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun err_cmd_poll:
826*4882a593Smuzhiyun 	mthca_cmd_use_polling(dev);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun err_eq_table_free:
829*4882a593Smuzhiyun 	mthca_cleanup_eq_table(dev);
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun err_pd_free:
832*4882a593Smuzhiyun 	mthca_pd_free(dev, &dev->driver_pd);
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun err_mr_table_free:
835*4882a593Smuzhiyun 	mthca_cleanup_mr_table(dev);
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun err_pd_table_free:
838*4882a593Smuzhiyun 	mthca_cleanup_pd_table(dev);
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun err_kar_unmap:
841*4882a593Smuzhiyun 	iounmap(dev->kar);
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun err_uar_free:
844*4882a593Smuzhiyun 	mthca_uar_free(dev, &dev->driver_uar);
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun err_uar_table_free:
847*4882a593Smuzhiyun 	mthca_cleanup_uar_table(dev);
848*4882a593Smuzhiyun 	return err;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun 
mthca_enable_msi_x(struct mthca_dev * mdev)851*4882a593Smuzhiyun static int mthca_enable_msi_x(struct mthca_dev *mdev)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun 	int err;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	err = pci_alloc_irq_vectors(mdev->pdev, 3, 3, PCI_IRQ_MSIX);
856*4882a593Smuzhiyun 	if (err < 0)
857*4882a593Smuzhiyun 		return err;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector =
860*4882a593Smuzhiyun 			pci_irq_vector(mdev->pdev, 0);
861*4882a593Smuzhiyun 	mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector =
862*4882a593Smuzhiyun 			pci_irq_vector(mdev->pdev, 1);
863*4882a593Smuzhiyun 	mdev->eq_table.eq[MTHCA_EQ_CMD  ].msi_x_vector =
864*4882a593Smuzhiyun 			pci_irq_vector(mdev->pdev, 2);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	return 0;
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun /* Types of supported HCA */
870*4882a593Smuzhiyun enum {
871*4882a593Smuzhiyun 	TAVOR,			/* MT23108                        */
872*4882a593Smuzhiyun 	ARBEL_COMPAT,		/* MT25208 in Tavor compat mode   */
873*4882a593Smuzhiyun 	ARBEL_NATIVE,		/* MT25208 with extended features */
874*4882a593Smuzhiyun 	SINAI			/* MT25204 */
875*4882a593Smuzhiyun };
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun #define MTHCA_FW_VER(major, minor, subminor) \
878*4882a593Smuzhiyun 	(((u64) (major) << 32) | ((u64) (minor) << 16) | (u64) (subminor))
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun static struct {
881*4882a593Smuzhiyun 	u64 latest_fw;
882*4882a593Smuzhiyun 	u32 flags;
883*4882a593Smuzhiyun } mthca_hca_table[] = {
884*4882a593Smuzhiyun 	[TAVOR]        = { .latest_fw = MTHCA_FW_VER(3, 5, 0),
885*4882a593Smuzhiyun 			   .flags     = 0 },
886*4882a593Smuzhiyun 	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 8, 200),
887*4882a593Smuzhiyun 			   .flags     = MTHCA_FLAG_PCIE },
888*4882a593Smuzhiyun 	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 3, 0),
889*4882a593Smuzhiyun 			   .flags     = MTHCA_FLAG_MEMFREE |
890*4882a593Smuzhiyun 					MTHCA_FLAG_PCIE },
891*4882a593Smuzhiyun 	[SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 2, 0),
892*4882a593Smuzhiyun 			   .flags     = MTHCA_FLAG_MEMFREE |
893*4882a593Smuzhiyun 					MTHCA_FLAG_PCIE    |
894*4882a593Smuzhiyun 					MTHCA_FLAG_SINAI_OPT }
895*4882a593Smuzhiyun };
896*4882a593Smuzhiyun 
__mthca_init_one(struct pci_dev * pdev,int hca_type)897*4882a593Smuzhiyun static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun 	int ddr_hidden = 0;
900*4882a593Smuzhiyun 	int err;
901*4882a593Smuzhiyun 	struct mthca_dev *mdev;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	printk(KERN_INFO PFX "Initializing %s\n",
904*4882a593Smuzhiyun 	       pci_name(pdev));
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	err = pci_enable_device(pdev);
907*4882a593Smuzhiyun 	if (err) {
908*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Cannot enable PCI device, "
909*4882a593Smuzhiyun 			"aborting.\n");
910*4882a593Smuzhiyun 		return err;
911*4882a593Smuzhiyun 	}
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	/*
914*4882a593Smuzhiyun 	 * Check for BARs.  We expect 0: 1MB, 2: 8MB, 4: DDR (may not
915*4882a593Smuzhiyun 	 * be present)
916*4882a593Smuzhiyun 	 */
917*4882a593Smuzhiyun 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
918*4882a593Smuzhiyun 	    pci_resource_len(pdev, 0) != 1 << 20) {
919*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Missing DCS, aborting.\n");
920*4882a593Smuzhiyun 		err = -ENODEV;
921*4882a593Smuzhiyun 		goto err_disable_pdev;
922*4882a593Smuzhiyun 	}
923*4882a593Smuzhiyun 	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
924*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Missing UAR, aborting.\n");
925*4882a593Smuzhiyun 		err = -ENODEV;
926*4882a593Smuzhiyun 		goto err_disable_pdev;
927*4882a593Smuzhiyun 	}
928*4882a593Smuzhiyun 	if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM))
929*4882a593Smuzhiyun 		ddr_hidden = 1;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	err = pci_request_regions(pdev, DRV_NAME);
932*4882a593Smuzhiyun 	if (err) {
933*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Cannot obtain PCI resources, "
934*4882a593Smuzhiyun 			"aborting.\n");
935*4882a593Smuzhiyun 		goto err_disable_pdev;
936*4882a593Smuzhiyun 	}
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 	pci_set_master(pdev);
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
941*4882a593Smuzhiyun 	if (err) {
942*4882a593Smuzhiyun 		dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n");
943*4882a593Smuzhiyun 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
944*4882a593Smuzhiyun 		if (err) {
945*4882a593Smuzhiyun 			dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n");
946*4882a593Smuzhiyun 			goto err_free_res;
947*4882a593Smuzhiyun 		}
948*4882a593Smuzhiyun 	}
949*4882a593Smuzhiyun 	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
950*4882a593Smuzhiyun 	if (err) {
951*4882a593Smuzhiyun 		dev_warn(&pdev->dev, "Warning: couldn't set 64-bit "
952*4882a593Smuzhiyun 			 "consistent PCI DMA mask.\n");
953*4882a593Smuzhiyun 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
954*4882a593Smuzhiyun 		if (err) {
955*4882a593Smuzhiyun 			dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, "
956*4882a593Smuzhiyun 				"aborting.\n");
957*4882a593Smuzhiyun 			goto err_free_res;
958*4882a593Smuzhiyun 		}
959*4882a593Smuzhiyun 	}
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	/* We can handle large RDMA requests, so allow larger segments. */
962*4882a593Smuzhiyun 	dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	mdev = ib_alloc_device(mthca_dev, ib_dev);
965*4882a593Smuzhiyun 	if (!mdev) {
966*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Device struct alloc failed, "
967*4882a593Smuzhiyun 			"aborting.\n");
968*4882a593Smuzhiyun 		err = -ENOMEM;
969*4882a593Smuzhiyun 		goto err_free_res;
970*4882a593Smuzhiyun 	}
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	mdev->pdev = pdev;
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	mdev->mthca_flags = mthca_hca_table[hca_type].flags;
975*4882a593Smuzhiyun 	if (ddr_hidden)
976*4882a593Smuzhiyun 		mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	/*
979*4882a593Smuzhiyun 	 * Now reset the HCA before we touch the PCI capabilities or
980*4882a593Smuzhiyun 	 * attempt a firmware command, since a boot ROM may have left
981*4882a593Smuzhiyun 	 * the HCA in an undefined state.
982*4882a593Smuzhiyun 	 */
983*4882a593Smuzhiyun 	err = mthca_reset(mdev);
984*4882a593Smuzhiyun 	if (err) {
985*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to reset HCA, aborting.\n");
986*4882a593Smuzhiyun 		goto err_free_dev;
987*4882a593Smuzhiyun 	}
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	err = mthca_cmd_init(mdev);
990*4882a593Smuzhiyun 	if (err) {
991*4882a593Smuzhiyun 		mthca_err(mdev, "Failed to init command interface, aborting.\n");
992*4882a593Smuzhiyun 		goto err_free_dev;
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	err = mthca_tune_pci(mdev);
996*4882a593Smuzhiyun 	if (err)
997*4882a593Smuzhiyun 		goto err_cmd;
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun 	err = mthca_init_hca(mdev);
1000*4882a593Smuzhiyun 	if (err)
1001*4882a593Smuzhiyun 		goto err_cmd;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	if (mdev->fw_ver < mthca_hca_table[hca_type].latest_fw) {
1004*4882a593Smuzhiyun 		mthca_warn(mdev, "HCA FW version %d.%d.%03d is old (%d.%d.%03d is current).\n",
1005*4882a593Smuzhiyun 			   (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff,
1006*4882a593Smuzhiyun 			   (int) (mdev->fw_ver & 0xffff),
1007*4882a593Smuzhiyun 			   (int) (mthca_hca_table[hca_type].latest_fw >> 32),
1008*4882a593Smuzhiyun 			   (int) (mthca_hca_table[hca_type].latest_fw >> 16) & 0xffff,
1009*4882a593Smuzhiyun 			   (int) (mthca_hca_table[hca_type].latest_fw & 0xffff));
1010*4882a593Smuzhiyun 		mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n");
1011*4882a593Smuzhiyun 	}
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	if (msi_x && !mthca_enable_msi_x(mdev))
1014*4882a593Smuzhiyun 		mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	err = mthca_setup_hca(mdev);
1017*4882a593Smuzhiyun 	if (err == -EBUSY && (mdev->mthca_flags & MTHCA_FLAG_MSI_X)) {
1018*4882a593Smuzhiyun 		pci_free_irq_vectors(pdev);
1019*4882a593Smuzhiyun 		mdev->mthca_flags &= ~MTHCA_FLAG_MSI_X;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 		err = mthca_setup_hca(mdev);
1022*4882a593Smuzhiyun 	}
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	if (err)
1025*4882a593Smuzhiyun 		goto err_close;
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun 	err = mthca_register_device(mdev);
1028*4882a593Smuzhiyun 	if (err)
1029*4882a593Smuzhiyun 		goto err_cleanup;
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	err = mthca_create_agents(mdev);
1032*4882a593Smuzhiyun 	if (err)
1033*4882a593Smuzhiyun 		goto err_unregister;
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun 	pci_set_drvdata(pdev, mdev);
1036*4882a593Smuzhiyun 	mdev->hca_type = hca_type;
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 	mdev->active = true;
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	return 0;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun err_unregister:
1043*4882a593Smuzhiyun 	mthca_unregister_device(mdev);
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun err_cleanup:
1046*4882a593Smuzhiyun 	mthca_cleanup_mcg_table(mdev);
1047*4882a593Smuzhiyun 	mthca_cleanup_av_table(mdev);
1048*4882a593Smuzhiyun 	mthca_cleanup_qp_table(mdev);
1049*4882a593Smuzhiyun 	mthca_cleanup_srq_table(mdev);
1050*4882a593Smuzhiyun 	mthca_cleanup_cq_table(mdev);
1051*4882a593Smuzhiyun 	mthca_cmd_use_polling(mdev);
1052*4882a593Smuzhiyun 	mthca_cleanup_eq_table(mdev);
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun 	mthca_pd_free(mdev, &mdev->driver_pd);
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	mthca_cleanup_mr_table(mdev);
1057*4882a593Smuzhiyun 	mthca_cleanup_pd_table(mdev);
1058*4882a593Smuzhiyun 	mthca_cleanup_uar_table(mdev);
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun err_close:
1061*4882a593Smuzhiyun 	if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
1062*4882a593Smuzhiyun 		pci_free_irq_vectors(pdev);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	mthca_close_hca(mdev);
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun err_cmd:
1067*4882a593Smuzhiyun 	mthca_cmd_cleanup(mdev);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun err_free_dev:
1070*4882a593Smuzhiyun 	ib_dealloc_device(&mdev->ib_dev);
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun err_free_res:
1073*4882a593Smuzhiyun 	pci_release_regions(pdev);
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun err_disable_pdev:
1076*4882a593Smuzhiyun 	pci_disable_device(pdev);
1077*4882a593Smuzhiyun 	pci_set_drvdata(pdev, NULL);
1078*4882a593Smuzhiyun 	return err;
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun 
__mthca_remove_one(struct pci_dev * pdev)1081*4882a593Smuzhiyun static void __mthca_remove_one(struct pci_dev *pdev)
1082*4882a593Smuzhiyun {
1083*4882a593Smuzhiyun 	struct mthca_dev *mdev = pci_get_drvdata(pdev);
1084*4882a593Smuzhiyun 	int p;
1085*4882a593Smuzhiyun 
1086*4882a593Smuzhiyun 	if (mdev) {
1087*4882a593Smuzhiyun 		mthca_free_agents(mdev);
1088*4882a593Smuzhiyun 		mthca_unregister_device(mdev);
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 		for (p = 1; p <= mdev->limits.num_ports; ++p)
1091*4882a593Smuzhiyun 			mthca_CLOSE_IB(mdev, p);
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 		mthca_cleanup_mcg_table(mdev);
1094*4882a593Smuzhiyun 		mthca_cleanup_av_table(mdev);
1095*4882a593Smuzhiyun 		mthca_cleanup_qp_table(mdev);
1096*4882a593Smuzhiyun 		mthca_cleanup_srq_table(mdev);
1097*4882a593Smuzhiyun 		mthca_cleanup_cq_table(mdev);
1098*4882a593Smuzhiyun 		mthca_cmd_use_polling(mdev);
1099*4882a593Smuzhiyun 		mthca_cleanup_eq_table(mdev);
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 		mthca_pd_free(mdev, &mdev->driver_pd);
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 		mthca_cleanup_mr_table(mdev);
1104*4882a593Smuzhiyun 		mthca_cleanup_pd_table(mdev);
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 		iounmap(mdev->kar);
1107*4882a593Smuzhiyun 		mthca_uar_free(mdev, &mdev->driver_uar);
1108*4882a593Smuzhiyun 		mthca_cleanup_uar_table(mdev);
1109*4882a593Smuzhiyun 		mthca_close_hca(mdev);
1110*4882a593Smuzhiyun 		mthca_cmd_cleanup(mdev);
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
1113*4882a593Smuzhiyun 			pci_free_irq_vectors(pdev);
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 		ib_dealloc_device(&mdev->ib_dev);
1116*4882a593Smuzhiyun 		pci_release_regions(pdev);
1117*4882a593Smuzhiyun 		pci_disable_device(pdev);
1118*4882a593Smuzhiyun 		pci_set_drvdata(pdev, NULL);
1119*4882a593Smuzhiyun 	}
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun 
__mthca_restart_one(struct pci_dev * pdev)1122*4882a593Smuzhiyun int __mthca_restart_one(struct pci_dev *pdev)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun 	struct mthca_dev *mdev;
1125*4882a593Smuzhiyun 	int hca_type;
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	mdev = pci_get_drvdata(pdev);
1128*4882a593Smuzhiyun 	if (!mdev)
1129*4882a593Smuzhiyun 		return -ENODEV;
1130*4882a593Smuzhiyun 	hca_type = mdev->hca_type;
1131*4882a593Smuzhiyun 	__mthca_remove_one(pdev);
1132*4882a593Smuzhiyun 	return __mthca_init_one(pdev, hca_type);
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
mthca_init_one(struct pci_dev * pdev,const struct pci_device_id * id)1135*4882a593Smuzhiyun static int mthca_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun 	int ret;
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	mutex_lock(&mthca_device_mutex);
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	printk_once(KERN_INFO "%s", mthca_version);
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) {
1144*4882a593Smuzhiyun 		printk(KERN_ERR PFX "%s has invalid driver data %lx\n",
1145*4882a593Smuzhiyun 		       pci_name(pdev), id->driver_data);
1146*4882a593Smuzhiyun 		mutex_unlock(&mthca_device_mutex);
1147*4882a593Smuzhiyun 		return -ENODEV;
1148*4882a593Smuzhiyun 	}
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	ret = __mthca_init_one(pdev, id->driver_data);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	mutex_unlock(&mthca_device_mutex);
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	return ret;
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun 
mthca_remove_one(struct pci_dev * pdev)1157*4882a593Smuzhiyun static void mthca_remove_one(struct pci_dev *pdev)
1158*4882a593Smuzhiyun {
1159*4882a593Smuzhiyun 	mutex_lock(&mthca_device_mutex);
1160*4882a593Smuzhiyun 	__mthca_remove_one(pdev);
1161*4882a593Smuzhiyun 	mutex_unlock(&mthca_device_mutex);
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun 
1164*4882a593Smuzhiyun static const struct pci_device_id mthca_pci_table[] = {
1165*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR),
1166*4882a593Smuzhiyun 	  .driver_data = TAVOR },
1167*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_TAVOR),
1168*4882a593Smuzhiyun 	  .driver_data = TAVOR },
1169*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT),
1170*4882a593Smuzhiyun 	  .driver_data = ARBEL_COMPAT },
1171*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT),
1172*4882a593Smuzhiyun 	  .driver_data = ARBEL_COMPAT },
1173*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL),
1174*4882a593Smuzhiyun 	  .driver_data = ARBEL_NATIVE },
1175*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL),
1176*4882a593Smuzhiyun 	  .driver_data = ARBEL_NATIVE },
1177*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI),
1178*4882a593Smuzhiyun 	  .driver_data = SINAI },
1179*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI),
1180*4882a593Smuzhiyun 	  .driver_data = SINAI },
1181*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI_OLD),
1182*4882a593Smuzhiyun 	  .driver_data = SINAI },
1183*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI_OLD),
1184*4882a593Smuzhiyun 	  .driver_data = SINAI },
1185*4882a593Smuzhiyun 	{ 0, }
1186*4882a593Smuzhiyun };
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, mthca_pci_table);
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun static struct pci_driver mthca_driver = {
1191*4882a593Smuzhiyun 	.name		= DRV_NAME,
1192*4882a593Smuzhiyun 	.id_table	= mthca_pci_table,
1193*4882a593Smuzhiyun 	.probe		= mthca_init_one,
1194*4882a593Smuzhiyun 	.remove		= mthca_remove_one,
1195*4882a593Smuzhiyun };
1196*4882a593Smuzhiyun 
__mthca_check_profile_val(const char * name,int * pval,int pval_default)1197*4882a593Smuzhiyun static void __init __mthca_check_profile_val(const char *name, int *pval,
1198*4882a593Smuzhiyun 					     int pval_default)
1199*4882a593Smuzhiyun {
1200*4882a593Smuzhiyun 	/* value must be positive and power of 2 */
1201*4882a593Smuzhiyun 	int old_pval = *pval;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	if (old_pval <= 0)
1204*4882a593Smuzhiyun 		*pval = pval_default;
1205*4882a593Smuzhiyun 	else
1206*4882a593Smuzhiyun 		*pval = roundup_pow_of_two(old_pval);
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	if (old_pval != *pval) {
1209*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "Invalid value %d for %s in module parameter.\n",
1210*4882a593Smuzhiyun 		       old_pval, name);
1211*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "Corrected %s to %d.\n", name, *pval);
1212*4882a593Smuzhiyun 	}
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun #define mthca_check_profile_val(name, default)				\
1216*4882a593Smuzhiyun 	__mthca_check_profile_val(#name, &hca_profile.name, default)
1217*4882a593Smuzhiyun 
mthca_validate_profile(void)1218*4882a593Smuzhiyun static void __init mthca_validate_profile(void)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun 	mthca_check_profile_val(num_qp,            MTHCA_DEFAULT_NUM_QP);
1221*4882a593Smuzhiyun 	mthca_check_profile_val(rdb_per_qp,        MTHCA_DEFAULT_RDB_PER_QP);
1222*4882a593Smuzhiyun 	mthca_check_profile_val(num_cq,            MTHCA_DEFAULT_NUM_CQ);
1223*4882a593Smuzhiyun 	mthca_check_profile_val(num_mcg, 	   MTHCA_DEFAULT_NUM_MCG);
1224*4882a593Smuzhiyun 	mthca_check_profile_val(num_mpt, 	   MTHCA_DEFAULT_NUM_MPT);
1225*4882a593Smuzhiyun 	mthca_check_profile_val(num_mtt, 	   MTHCA_DEFAULT_NUM_MTT);
1226*4882a593Smuzhiyun 	mthca_check_profile_val(num_udav,          MTHCA_DEFAULT_NUM_UDAV);
1227*4882a593Smuzhiyun 	mthca_check_profile_val(fmr_reserved_mtts, MTHCA_DEFAULT_NUM_RESERVED_MTTS);
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	if (hca_profile.fmr_reserved_mtts >= hca_profile.num_mtt) {
1230*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "Invalid fmr_reserved_mtts module parameter %d.\n",
1231*4882a593Smuzhiyun 		       hca_profile.fmr_reserved_mtts);
1232*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "(Must be smaller than num_mtt %d)\n",
1233*4882a593Smuzhiyun 		       hca_profile.num_mtt);
1234*4882a593Smuzhiyun 		hca_profile.fmr_reserved_mtts = hca_profile.num_mtt / 2;
1235*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "Corrected fmr_reserved_mtts to %d.\n",
1236*4882a593Smuzhiyun 		       hca_profile.fmr_reserved_mtts);
1237*4882a593Smuzhiyun 	}
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun 	if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) {
1240*4882a593Smuzhiyun 		printk(KERN_WARNING PFX "bad log_mtts_per_seg (%d). Using default - %d\n",
1241*4882a593Smuzhiyun 		       log_mtts_per_seg, ilog2(MTHCA_MTT_SEG_SIZE / 8));
1242*4882a593Smuzhiyun 		log_mtts_per_seg = ilog2(MTHCA_MTT_SEG_SIZE / 8);
1243*4882a593Smuzhiyun 	}
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun 
mthca_init(void)1246*4882a593Smuzhiyun static int __init mthca_init(void)
1247*4882a593Smuzhiyun {
1248*4882a593Smuzhiyun 	int ret;
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	mthca_validate_profile();
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun 	ret = mthca_catas_init();
1253*4882a593Smuzhiyun 	if (ret)
1254*4882a593Smuzhiyun 		return ret;
1255*4882a593Smuzhiyun 
1256*4882a593Smuzhiyun 	ret = pci_register_driver(&mthca_driver);
1257*4882a593Smuzhiyun 	if (ret < 0) {
1258*4882a593Smuzhiyun 		mthca_catas_cleanup();
1259*4882a593Smuzhiyun 		return ret;
1260*4882a593Smuzhiyun 	}
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	return 0;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun 
mthca_cleanup(void)1265*4882a593Smuzhiyun static void __exit mthca_cleanup(void)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun 	pci_unregister_driver(&mthca_driver);
1268*4882a593Smuzhiyun 	mthca_catas_cleanup();
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun module_init(mthca_init);
1272*4882a593Smuzhiyun module_exit(mthca_cleanup);
1273