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