70a72e16075e6d8d33dd00cca484b3e56c6787ac
[mirror/winof/.git] / hw / mthca / kernel / mthca_main.c
1 /*\r
2  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.\r
3  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.\r
4  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.\r
5  *\r
6  * This software is available to you under a choice of one of two\r
7  * licenses.  You may choose to be licensed under the terms of the GNU\r
8  * General Public License (GPL) Version 2, available from the file\r
9  * COPYING in the main directory of this source tree, or the\r
10  * OpenIB.org BSD license below:\r
11  *\r
12  *     Redistribution and use in source and binary forms, with or\r
13  *     without modification, are permitted provided that the following\r
14  *     conditions are met:\r
15  *\r
16  *      - Redistributions of source code must retain the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer.\r
19  *\r
20  *      - Redistributions in binary form must reproduce the above\r
21  *        copyright notice, this list of conditions and the following\r
22  *        disclaimer in the documentation and/or other materials\r
23  *        provided with the distribution.\r
24  *\r
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
32  * SOFTWARE.\r
33  *\r
34  * $Id$\r
35  */\r
36 \r
37 #include "mthca_dev.h"\r
38 #if defined(EVENT_TRACING)\r
39 #ifdef offsetof\r
40 #undef offsetof\r
41 #endif\r
42 #include "mthca_main.tmh"\r
43 #endif\r
44 #include "mthca_config_reg.h"\r
45 #include "mthca_cmd.h"\r
46 #include "mthca_profile.h"\r
47 #include "mthca_memfree.h"\r
48 \r
49 static const char mthca_version[] =\r
50         DRV_NAME ": HCA Driver v"\r
51         DRV_VERSION " (" DRV_RELDATE ")";\r
52 \r
53 static struct mthca_profile default_profile = {\r
54         1 << 16,                // num_qp\r
55         4,                                      // rdb_per_qp\r
56         0,                              // num_srq\r
57         1 << 16,                // num_cq\r
58         1 << 13,                // num_mcg\r
59         1 << 17,                // num_mpt\r
60         1 << 20,                // num_mtt\r
61         1 << 15,                // num_udav (Tavor only)\r
62         0,                                      // num_uar\r
63         1 << 18,                // uarc_size (Arbel only)\r
64         1 << 18,                // fmr_reserved_mtts (Tavor only)\r
65 };\r
66 \r
67 /* Types of supported HCA */\r
68 enum __hca_type {\r
69         TAVOR,                  /* MT23108                        */\r
70         ARBEL_COMPAT,           /* MT25208 in Tavor compat mode   */\r
71         ARBEL_NATIVE,           /* MT25218 with extended features */\r
72         SINAI,                  /* MT25204 */\r
73         LIVEFISH                /* a burning device */\r
74 };\r
75 \r
76 #define MTHCA_FW_VER(major, minor, subminor) \\r
77         (((u64) (major) << 32) | ((u64) (minor) << 16) | (u64) (subminor))\r
78 \r
79 static struct {\r
80         u64 max_unsupported_fw;\r
81         u64 min_supported_fw;\r
82         int is_memfree;\r
83         int is_pcie;\r
84 } mthca_hca_table[] = {\r
85         { MTHCA_FW_VER(3, 3, 2), MTHCA_FW_VER(3, 4, 0), 0, 0 }, /* TAVOR */\r
86         { MTHCA_FW_VER(4, 7, 0), MTHCA_FW_VER(4, 7, 400), 0, 1 },       /* ARBEL_COMPAT */\r
87         { MTHCA_FW_VER(5, 1, 0), MTHCA_FW_VER(5, 1, 400), 1, 1 },       /* ARBEL_NATIVE */\r
88         { MTHCA_FW_VER(1, 0, 800), MTHCA_FW_VER(1, 1, 0), 1, 1 },       /* SINAI */\r
89         { MTHCA_FW_VER(0, 0, 0), MTHCA_FW_VER(0, 0, 0), 0, 0 }          /* LIVEFISH */\r
90 };\r
91 \r
92 \r
93 #define HCA(v, d, t) \\r
94         { PCI_VENDOR_ID_##v,    PCI_DEVICE_ID_MELLANOX_##d, t }\r
95 \r
96 static struct pci_device_id {\r
97         unsigned                vendor;\r
98         unsigned                device;\r
99         enum __hca_type driver_data;\r
100 } mthca_pci_table[] = {\r
101         HCA(MELLANOX, TAVOR,        TAVOR),\r
102         HCA(MELLANOX, ARBEL_COMPAT, ARBEL_COMPAT),\r
103         HCA(MELLANOX, ARBEL,        ARBEL_NATIVE),\r
104         HCA(MELLANOX, SINAI_OLD,    SINAI),\r
105         HCA(MELLANOX, SINAI,        SINAI),\r
106         HCA(TOPSPIN,  TAVOR,        TAVOR),\r
107         HCA(TOPSPIN,  ARBEL_COMPAT, TAVOR),\r
108         HCA(TOPSPIN,  ARBEL,        ARBEL_NATIVE),\r
109         HCA(TOPSPIN,  SINAI_OLD,    SINAI),\r
110         HCA(TOPSPIN,  SINAI,        SINAI),\r
111         // live fishes\r
112         HCA(MELLANOX, TAVOR_BD, LIVEFISH),\r
113         HCA(MELLANOX, ARBEL_BD,         LIVEFISH),\r
114         HCA(MELLANOX, SINAI_OLD_BD,     LIVEFISH),\r
115         HCA(MELLANOX, SINAI_BD,         LIVEFISH),\r
116         HCA(TOPSPIN, TAVOR_BD,          LIVEFISH),\r
117         HCA(TOPSPIN, ARBEL_BD,          LIVEFISH),\r
118         HCA(TOPSPIN, SINAI_OLD_BD,      LIVEFISH),\r
119         HCA(TOPSPIN, SINAI_BD,          LIVEFISH),\r
120 };\r
121 #define MTHCA_PCI_TABLE_SIZE (sizeof(mthca_pci_table)/sizeof(struct pci_device_id))\r
122 \r
123 // wrapper to driver's hca_tune_pci\r
124 static NTSTATUS mthca_tune_pci(struct mthca_dev *mdev)\r
125 {\r
126         PDEVICE_OBJECT pdo = mdev->ext->cl_ext.p_self_do;\r
127         return hca_tune_pci(pdo, &mdev->uplink_info);\r
128 }\r
129 \r
130 int mthca_get_dev_info(struct mthca_dev *mdev, __be64 *node_guid, u32 *hw_id)\r
131 {\r
132         struct ib_device_attr props;\r
133         struct ib_device *ib_dev = &mdev->ib_dev;\r
134         int err = (ib_dev->query_device )(ib_dev, &props );\r
135 \r
136         if (err) {\r
137                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("can't get guid - mthca_query_port() failed (%08X)\n", err ));\r
138                 return err;\r
139         }\r
140 \r
141         //TODO: do we need to convert GUID to LE by cl_ntoh64(x) ?\r
142         *node_guid = ib_dev->node_guid;\r
143         *hw_id = props.hw_ver;\r
144         return 0;\r
145 }\r
146 \r
147 static struct pci_device_id * mthca_find_pci_dev(unsigned ven_id, unsigned dev_id)\r
148 {\r
149         struct pci_device_id *p_id = mthca_pci_table;\r
150         int i;\r
151 \r
152         // find p_id (appropriate line in mthca_pci_table)\r
153         for (i = 0; i < MTHCA_PCI_TABLE_SIZE; ++i, ++p_id) {\r
154                 if (p_id->device == dev_id && p_id->vendor ==  ven_id)\r
155                         return p_id;\r
156         }\r
157         return NULL;\r
158 }\r
159 \r
160 \r
161 static int  mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)\r
162 {\r
163         int err;\r
164         u8 status;\r
165 \r
166         err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);\r
167         if (err) {\r
168                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_DEV_LIM command failed, aborting.\n"));\r
169                 return err;\r
170         }\r
171         if (status) {\r
172                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("QUERY_DEV_LIM returned status 0x%02x, "\r
173                           "aborting.\n", status));\r
174                 return -EINVAL;\r
175         }\r
176         if (dev_lim->min_page_sz > PAGE_SIZE) {\r
177                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("HCA minimum page size of %d bigger than "\r
178                           "kernel PAGE_SIZE of %ld, aborting.\n",\r
179                           dev_lim->min_page_sz, PAGE_SIZE));\r
180                 return -ENODEV;\r
181         }\r
182         if (dev_lim->num_ports > MTHCA_MAX_PORTS) {\r
183                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("HCA has %d ports, but we only support %d, "\r
184                           "aborting.\n",\r
185                           dev_lim->num_ports, MTHCA_MAX_PORTS));\r
186                 return -ENODEV;\r
187         }\r
188 \r
189         if (dev_lim->uar_size > (int)pci_resource_len(mdev, HCA_BAR_TYPE_UAR)) {\r
190                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW , ("HCA reported UAR size of 0x%x bigger than "\r
191                           "Bar%d size of 0x%lx, aborting.\n",\r
192                           dev_lim->uar_size, HCA_BAR_TYPE_UAR, \r
193                           (unsigned long)pci_resource_len(mdev, HCA_BAR_TYPE_UAR)));\r
194                 return -ENODEV;\r
195         }\r
196         \r
197 \r
198         mdev->limits.num_ports          = dev_lim->num_ports;\r
199         mdev->limits.vl_cap             = dev_lim->max_vl;\r
200         mdev->limits.mtu_cap            = dev_lim->max_mtu;\r
201         mdev->limits.gid_table_len      = dev_lim->max_gids;\r
202         mdev->limits.pkey_table_len     = dev_lim->max_pkeys;\r
203         mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;\r
204         mdev->limits.max_sg             = dev_lim->max_sg;\r
205         mdev->limits.max_wqes           = dev_lim->max_qp_sz;\r
206         mdev->limits.max_qp_init_rdma   = dev_lim->max_requester_per_qp;\r
207         mdev->limits.reserved_qps       = dev_lim->reserved_qps;\r
208         mdev->limits.max_srq_wqes       = dev_lim->max_srq_sz;\r
209         mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;\r
210         mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;\r
211         mdev->limits.max_desc_sz      = dev_lim->max_desc_sz;\r
212         mdev->limits.max_srq_sge        = mthca_max_srq_sge(mdev);\r
213         /*\r
214          * Subtract 1 from the limit because we need to allocate a\r
215          * spare CQE so the HCA HW can tell the difference between an\r
216          * empty CQ and a full CQ.\r
217          */\r
218         mdev->limits.max_cqes           = dev_lim->max_cq_sz - 1;\r
219         mdev->limits.reserved_cqs       = dev_lim->reserved_cqs;\r
220         mdev->limits.reserved_eqs       = dev_lim->reserved_eqs;\r
221         mdev->limits.reserved_mtts      = dev_lim->reserved_mtts;\r
222         mdev->limits.reserved_mrws      = dev_lim->reserved_mrws;\r
223         mdev->limits.reserved_uars      = dev_lim->reserved_uars;\r
224         mdev->limits.reserved_pds       = dev_lim->reserved_pds;\r
225         mdev->limits.port_width_cap     = (u8)dev_lim->max_port_width;\r
226         mdev->limits.page_size_cap      = !(u32)(dev_lim->min_page_sz - 1);\r
227         mdev->limits.flags                              = dev_lim->flags;\r
228         mdev->limits.num_avs = mthca_is_memfree(mdev) ? 0 : dev_lim->hca.tavor.max_avs;\r
229 \r
230         /* IB_DEVICE_RESIZE_MAX_WR not supported by driver.\r
231            May be doable since hardware supports it for SRQ.\r
232 \r
233            IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver.\r
234 \r
235            IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not\r
236            supported by driver. */\r
237         mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |\r
238                 IB_DEVICE_PORT_ACTIVE_EVENT |\r
239                 IB_DEVICE_SYS_IMAGE_GUID |\r
240                 IB_DEVICE_RC_RNR_NAK_GEN;\r
241 \r
242         if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR)\r
243                 mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;\r
244 \r
245         if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR)\r
246                 mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;\r
247 \r
248         if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI)\r
249                 mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI;\r
250 \r
251         if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG)\r
252                 mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;\r
253 \r
254         if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE)\r
255                 mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;\r
256 \r
257         if (dev_lim->flags & DEV_LIM_FLAG_SRQ)\r
258                 mdev->mthca_flags |= MTHCA_FLAG_SRQ;\r
259         \r
260         if (mthca_is_memfree(mdev)) {\r
261                 if (dev_lim->flags & DEV_LIM_FLAG_IPOIB_CSUM)\r
262                         mdev->device_cap_flags |= IB_DEVICE_IPOIB_CSUM; //IB_DEVICE_UD_IP_CSUM;\r
263         }\r
264 \r
265         return 0;\r
266 }\r
267 \r
268 static int  mthca_init_tavor(struct mthca_dev *mdev)\r
269 {\r
270         u8 status;\r
271         int err;\r
272         struct mthca_dev_lim        dev_lim;\r
273         struct mthca_profile        profile;\r
274         struct mthca_init_hca_param init_hca;\r
275 \r
276         err = mthca_SYS_EN(mdev, &status);\r
277         if (err) {\r
278                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("SYS_EN command failed, aborting.\n"));\r
279                 return err;\r
280         }\r
281         if (status) {\r
282                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("SYS_EN returned status 0x%02x, "\r
283                           "aborting.\n", status));\r
284                 return -EINVAL;\r
285         }\r
286 \r
287         err = mthca_QUERY_FW(mdev, &status);\r
288         if (err) {\r
289                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_FW command failed, aborting.\n"));\r
290                 goto err_disable;\r
291         }\r
292         if (status) {\r
293                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("QUERY_FW returned status 0x%02x, "\r
294                           "aborting.\n", status));\r
295                 err = -EINVAL;\r
296                 goto err_disable;\r
297         }\r
298         err = mthca_QUERY_DDR(mdev, &status);\r
299         if (err) {\r
300                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_DDR command failed, aborting.\n"));\r
301                 goto err_disable;\r
302         }\r
303         if (status) {\r
304                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,( "QUERY_DDR returned status 0x%02x, "\r
305                           "aborting.\n", status));\r
306                 err = -EINVAL;\r
307                 goto err_disable;\r
308         }\r
309 \r
310         err = mthca_dev_lim(mdev, &dev_lim);\r
311         if (err) {\r
312                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,( "QUERY_DEV_LIM command failed, aborting.\n"));\r
313                 goto err_disable;\r
314         }\r
315 \r
316         profile = default_profile;\r
317         profile.num_uar   = dev_lim.uar_size / PAGE_SIZE;\r
318         profile.uarc_size = 0;\r
319 \r
320         /* correct default profile */\r
321         if ( g_profile_qp_num != 0 ) \r
322                 profile.num_qp = g_profile_qp_num;\r
323                 \r
324         if ( g_profile_rd_out != 0xffffffff )\r
325                 profile.rdb_per_qp = g_profile_rd_out;\r
326 \r
327         if (mdev->mthca_flags & MTHCA_FLAG_SRQ)\r
328                 profile.num_srq = dev_lim.max_srqs;\r
329 \r
330         err = (int)mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);\r
331         if (err < 0)\r
332                 goto err_disable;\r
333 \r
334         err = (int)mthca_INIT_HCA(mdev, &init_hca, &status);\r
335         if (err) {\r
336                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("INIT_HCA command failed, aborting.\n"));\r
337                 goto err_disable;\r
338         }\r
339         if (status) {\r
340                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("INIT_HCA returned status 0x%02x, "\r
341                           "aborting.\n", status));\r
342                 err = -EINVAL;\r
343                 goto err_disable;\r
344         }\r
345 \r
346         return 0;\r
347 \r
348 err_disable:\r
349         mthca_SYS_DIS(mdev, &status);\r
350 \r
351         return err;\r
352 }\r
353 \r
354 static int  mthca_load_fw(struct mthca_dev *mdev)\r
355 {\r
356         u8 status;\r
357         int err;\r
358 \r
359         /* FIXME: use HCA-attached memory for FW if present */\r
360 \r
361         mdev->fw.arbel.fw_icm =\r
362                 mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages,\r
363                                 GFP_HIGHUSER | __GFP_NOWARN);\r
364         if (!mdev->fw.arbel.fw_icm) {\r
365                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Couldn't allocate FW area, aborting.\n"));\r
366                 return -ENOMEM;\r
367         }\r
368 \r
369         err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status);\r
370         if (err) {\r
371                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("MAP_FA command failed, aborting.\n"));\r
372                 goto err_free;\r
373         }\r
374         if (status) {\r
375                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("MAP_FA returned status 0x%02x, aborting.\n", status));\r
376                 err = -EINVAL;\r
377                 goto err_free;\r
378         }\r
379         err = mthca_RUN_FW(mdev, &status);\r
380         if (err) {\r
381                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("RUN_FW command failed, aborting.\n"));\r
382                 goto err_unmap_fa;\r
383         }\r
384         if (status) {\r
385                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("RUN_FW returned status 0x%02x, aborting.\n", status));\r
386                 err = -EINVAL;\r
387                 goto err_unmap_fa;\r
388         }\r
389 \r
390         return 0;\r
391 \r
392 err_unmap_fa:\r
393         mthca_UNMAP_FA(mdev, &status);\r
394 \r
395 err_free:\r
396         mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);\r
397         return err;\r
398 }\r
399 \r
400 static int  mthca_init_icm(struct mthca_dev *mdev,\r
401                                     struct mthca_dev_lim *dev_lim,\r
402                                     struct mthca_init_hca_param *init_hca,\r
403                                     u64 icm_size)\r
404 {\r
405         u64 aux_pages;\r
406         u8 status;\r
407         int err;\r
408 \r
409         err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status);\r
410         if (err) {\r
411                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("SET_ICM_SIZE command failed, aborting.\n"));\r
412                 return err;\r
413         }\r
414         if (status) {\r
415                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("SET_ICM_SIZE returned status 0x%02x, "\r
416                           "aborting.\n", status));\r
417                 return -EINVAL;\r
418         }\r
419 \r
420         HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_LOW , ("%I64d KB of HCA context requires %I64d KB aux memory.\n",\r
421                   (u64) icm_size >> 10,\r
422                   (u64) aux_pages << 2));\r
423 \r
424         mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, (int)aux_pages,\r
425                                                  GFP_HIGHUSER | __GFP_NOWARN);\r
426         if (!mdev->fw.arbel.aux_icm) {\r
427                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Couldn't allocate aux memory, aborting.\n"));\r
428                 return -ENOMEM;\r
429         }\r
430 \r
431         err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status);\r
432         if (err) {\r
433                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("MAP_ICM_AUX command failed, aborting.\n"));\r
434                 goto err_free_aux;\r
435         }\r
436         if (status) {\r
437                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("MAP_ICM_AUX returned status 0x%02x, aborting.\n", status));\r
438                 err = -EINVAL;\r
439                 goto err_free_aux;\r
440         }\r
441 \r
442         err = mthca_map_eq_icm(mdev, init_hca->eqc_base);\r
443         if (err) {\r
444                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map EQ context memory, aborting.\n"));\r
445                 goto err_unmap_aux;\r
446         }\r
447 \r
448         /* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */\r
449         mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * MTHCA_MTT_SEG_SIZE,\r
450                                                          dma_get_cache_alignment()) / MTHCA_MTT_SEG_SIZE;\r
451         \r
452         mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,\r
453                                                          MTHCA_MTT_SEG_SIZE,\r
454                                                          mdev->limits.num_mtt_segs,\r
455                                                          mdev->limits.reserved_mtts, 1);\r
456         if (!mdev->mr_table.mtt_table) {\r
457                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map MTT context memory, aborting.\n"));\r
458                 err = -ENOMEM;\r
459                 goto err_unmap_eq;\r
460         }\r
461 \r
462         mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,\r
463                                                          dev_lim->mpt_entry_sz,\r
464                                                          mdev->limits.num_mpts,\r
465                                                          mdev->limits.reserved_mrws, 1);\r
466         if (!mdev->mr_table.mpt_table) {\r
467                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map MPT context memory, aborting.\n"));\r
468                 err = -ENOMEM;\r
469                 goto err_unmap_mtt;\r
470         }\r
471 \r
472         mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,\r
473                                                         dev_lim->qpc_entry_sz,\r
474                                                         mdev->limits.num_qps,\r
475                                                         mdev->limits.reserved_qps, 0);\r
476         if (!mdev->qp_table.qp_table) {\r
477                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map QP context memory, aborting.\n"));\r
478                 err = -ENOMEM;\r
479                 goto err_unmap_mpt;\r
480         }\r
481 \r
482         mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,\r
483                                                          dev_lim->eqpc_entry_sz,\r
484                                                          mdev->limits.num_qps,\r
485                                                          mdev->limits.reserved_qps, 0);\r
486         if (!mdev->qp_table.eqp_table) {\r
487                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map EQP context memory, aborting.\n"));\r
488                 err = -ENOMEM;\r
489                 goto err_unmap_qp;\r
490         }\r
491 \r
492         mdev->qp_table.rdb_table = mthca_alloc_icm_table(mdev, init_hca->rdb_base,\r
493                                                          MTHCA_RDB_ENTRY_SIZE,\r
494                                                          mdev->limits.num_qps <<\r
495                                                          mdev->qp_table.rdb_shift,\r
496                                                          0, 0);\r
497         if (!mdev->qp_table.rdb_table) {\r
498                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map RDB context memory, aborting\n"));\r
499                 err = -ENOMEM;\r
500                 goto err_unmap_eqp;\r
501         }\r
502 \r
503        mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,\r
504                                                     dev_lim->cqc_entry_sz,\r
505                                                     mdev->limits.num_cqs,\r
506                                                     mdev->limits.reserved_cqs, 0);\r
507         if (!mdev->cq_table.table) {\r
508                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map CQ context memory, aborting.\n"));\r
509                 err = -ENOMEM;\r
510                 goto err_unmap_rdb;\r
511         }\r
512 \r
513         if (mdev->mthca_flags & MTHCA_FLAG_SRQ) {\r
514                 mdev->srq_table.table =\r
515                         mthca_alloc_icm_table(mdev, init_hca->srqc_base,\r
516                                               dev_lim->srq_entry_sz,\r
517                                               mdev->limits.num_srqs,\r
518                                               mdev->limits.reserved_srqs, 0);\r
519                 if (!mdev->srq_table.table) {\r
520                         HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("Failed to map SRQ context memory, "\r
521                                   "aborting.\n"));\r
522                         err = -ENOMEM;\r
523                         goto err_unmap_cq;\r
524                 }\r
525         }\r
526 \r
527         /*\r
528          * It's not strictly required, but for simplicity just map the\r
529          * whole multicast group table now.  The table isn't very big\r
530          * and it's a lot easier than trying to track ref counts.\r
531          */\r
532         mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base,\r
533                                                       MTHCA_MGM_ENTRY_SIZE,\r
534                                                       mdev->limits.num_mgms +\r
535                                                       mdev->limits.num_amgms,\r
536                                                       mdev->limits.num_mgms +\r
537                                                       mdev->limits.num_amgms,\r
538                                                       0);\r
539         if (!mdev->mcg_table.table) {\r
540                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to map MCG context memory, aborting.\n"));\r
541                 err = -ENOMEM;\r
542                 goto err_unmap_srq;\r
543         }\r
544 \r
545         return 0;\r
546 \r
547 err_unmap_srq:\r
548         if (mdev->mthca_flags & MTHCA_FLAG_SRQ)\r
549                 mthca_free_icm_table(mdev, mdev->srq_table.table);\r
550 \r
551 err_unmap_cq:\r
552         mthca_free_icm_table(mdev, mdev->cq_table.table);\r
553 \r
554 err_unmap_rdb:\r
555         mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);\r
556 \r
557 err_unmap_eqp:\r
558         mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);\r
559 \r
560 err_unmap_qp:\r
561         mthca_free_icm_table(mdev, mdev->qp_table.qp_table);\r
562 \r
563 err_unmap_mpt:\r
564         mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);\r
565 \r
566 err_unmap_mtt:\r
567         mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);\r
568 \r
569 err_unmap_eq:\r
570         mthca_unmap_eq_icm(mdev);\r
571 \r
572 err_unmap_aux:\r
573         mthca_UNMAP_ICM_AUX(mdev, &status);\r
574 \r
575 err_free_aux:\r
576         mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);\r
577 \r
578         return err;\r
579 }\r
580 \r
581 static int  mthca_init_arbel(struct mthca_dev *mdev)\r
582 {\r
583         struct mthca_dev_lim        dev_lim;\r
584         struct mthca_profile        profile;\r
585         struct mthca_init_hca_param init_hca;\r
586         u64 icm_size;\r
587         u8 status;\r
588         int err;\r
589 \r
590         err = mthca_QUERY_FW(mdev, &status);\r
591         if (err) {\r
592                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_FW command failed, aborting.\n"));\r
593                 return err;\r
594         }\r
595         if (status) {\r
596                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("QUERY_FW returned status 0x%02x, "\r
597                           "aborting.\n", status));\r
598                 return -EINVAL;\r
599         }\r
600 \r
601         err = mthca_ENABLE_LAM(mdev, &status);\r
602         if (err) {\r
603                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("ENABLE_LAM command failed, aborting.\n"));\r
604                 return err;\r
605         }\r
606         if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) {\r
607                 HCA_PRINT(TRACE_LEVEL_INFORMATION   ,HCA_DBG_LOW   ,("No HCA-attached memory (running in MemFree mode)\n"));\r
608                 mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;\r
609         } else if (status) {\r
610                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("ENABLE_LAM returned status 0x%02x, "\r
611                           "aborting.\n", status));\r
612                 return -EINVAL;\r
613         }\r
614 \r
615         err = mthca_load_fw(mdev);\r
616         if (err) {\r
617                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to start FW, aborting.\n"));\r
618                 goto err_disable;\r
619         }\r
620 \r
621         err = mthca_dev_lim(mdev, &dev_lim);\r
622         if (err) {\r
623                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_DEV_LIM command failed, aborting.\n"));\r
624                 goto err_stop_fw;\r
625         }\r
626 \r
627         profile = default_profile;\r
628         profile.num_uar  = dev_lim.uar_size / PAGE_SIZE;\r
629         profile.num_udav = 0;\r
630         if (mdev->mthca_flags & MTHCA_FLAG_SRQ)\r
631                 profile.num_srq = dev_lim.max_srqs;\r
632 \r
633         /* correct default profile */\r
634         if ( g_profile_qp_num != 0 ) \r
635                 profile.num_qp = g_profile_qp_num;\r
636                 \r
637         if ( g_profile_rd_out != 0xffffffff )\r
638                 profile.rdb_per_qp = g_profile_rd_out;\r
639 \r
640         RtlZeroMemory( &init_hca, sizeof(init_hca));\r
641         icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);\r
642         if ((int) icm_size < 0) {\r
643                 err = (int)icm_size;\r
644                 goto err_stop_fw;\r
645         }\r
646 \r
647         err = mthca_init_icm(mdev, &dev_lim, &init_hca, icm_size);\r
648         if (err)\r
649                 goto err_stop_fw;\r
650 \r
651         err = mthca_INIT_HCA(mdev, &init_hca, &status);\r
652         if (err) {\r
653                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("INIT_HCA command failed, aborting.\n"));\r
654                 goto err_free_icm;\r
655         }\r
656         if (status) {\r
657                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("INIT_HCA returned status 0x%02x, "\r
658                           "aborting.\n", status));\r
659                 err = -EINVAL;\r
660                 goto err_free_icm;\r
661         }\r
662 \r
663         return 0;\r
664 \r
665 err_free_icm:\r
666         if (mdev->mthca_flags & MTHCA_FLAG_SRQ)\r
667                 mthca_free_icm_table(mdev, mdev->srq_table.table);\r
668         mthca_free_icm_table(mdev, mdev->cq_table.table);\r
669         mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);\r
670         mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);\r
671         mthca_free_icm_table(mdev, mdev->qp_table.qp_table);\r
672         mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);\r
673         mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);\r
674         mthca_unmap_eq_icm(mdev);\r
675 \r
676         mthca_UNMAP_ICM_AUX(mdev, &status);\r
677         mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);\r
678 \r
679 err_stop_fw:\r
680         mthca_UNMAP_FA(mdev, &status);\r
681         mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);\r
682 \r
683 err_disable:\r
684         if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))\r
685                 mthca_DISABLE_LAM(mdev, &status);\r
686 \r
687         return err;\r
688 }\r
689 \r
690 static void mthca_close_hca(struct mthca_dev *mdev)\r
691 {\r
692         u8 status;\r
693 \r
694         mthca_CLOSE_HCA(mdev, 0, &status);\r
695 \r
696         if (mthca_is_memfree(mdev)) {\r
697                 if (mdev->mthca_flags & MTHCA_FLAG_SRQ)\r
698                         mthca_free_icm_table(mdev, mdev->srq_table.table);\r
699                 mthca_free_icm_table(mdev, mdev->cq_table.table);\r
700                 mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);\r
701                 mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);\r
702                 mthca_free_icm_table(mdev, mdev->qp_table.qp_table);\r
703                 mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);\r
704                 mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);\r
705                 mthca_free_icm_table(mdev, mdev->mcg_table.table);\r
706                 mthca_unmap_eq_icm(mdev);\r
707 \r
708                 mthca_UNMAP_ICM_AUX(mdev, &status);\r
709                 mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);\r
710 \r
711                 mthca_UNMAP_FA(mdev, &status);\r
712                 mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);\r
713 \r
714                 if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))\r
715                         mthca_DISABLE_LAM(mdev, &status);\r
716         } else\r
717                 mthca_SYS_DIS(mdev, &status);\r
718 }\r
719 \r
720 static int  mthca_init_hca(struct mthca_dev *mdev)\r
721 {\r
722         u8 status;\r
723         int err;\r
724         struct mthca_adapter adapter;\r
725 \r
726         if (mthca_is_memfree(mdev))\r
727                 err = mthca_init_arbel(mdev);\r
728         else\r
729                 err = mthca_init_tavor(mdev);\r
730 \r
731         if (err)\r
732                 return err;\r
733 \r
734         err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);\r
735         if (err) {\r
736                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("QUERY_ADAPTER command failed, aborting.\n"));\r
737                 goto err_close;\r
738         }\r
739         if (status) {\r
740                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("QUERY_ADAPTER returned status 0x%02x, "\r
741                           "aborting.\n", status));\r
742                 err = -EINVAL;\r
743                 goto err_close;\r
744         }\r
745 \r
746         mdev->eq_table.inta_pin = adapter.inta_pin;\r
747         mdev->rev_id            = adapter.revision_id;\r
748         memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);\r
749 \r
750         return 0;\r
751 \r
752 err_close:\r
753         mthca_close_hca(mdev);\r
754         return err;\r
755 }\r
756 \r
757 static int  mthca_setup_hca(struct mthca_dev *mdev)\r
758 {\r
759         int err;\r
760         u8 status;\r
761 \r
762         MTHCA_INIT_DOORBELL_LOCK(&mdev->doorbell_lock);\r
763 \r
764         err = mthca_init_uar_table(mdev);\r
765         if (err) {\r
766                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
767                           "user access region table, aborting.\n"));\r
768                 return err;\r
769         }\r
770 \r
771         err = mthca_uar_alloc(mdev, &mdev->driver_uar);\r
772         if (err) {\r
773                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to allocate driver access region, "\r
774                           "aborting.\n"));\r
775                 goto err_uar_table_free;\r
776         }\r
777 \r
778         mdev->kar = ioremap((io_addr_t)mdev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE,&mdev->kar_size);\r
779         if (!mdev->kar) {\r
780                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Couldn't map kernel access region, "\r
781                           "aborting.\n"));\r
782                 err = -ENOMEM;\r
783                 goto err_uar_free;\r
784         }\r
785 \r
786         err = mthca_init_pd_table(mdev);\r
787         if (err) {\r
788                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
789                           "protection domain table, aborting.\n"));\r
790                 goto err_kar_unmap;\r
791         }\r
792 \r
793         err = mthca_init_mr_table(mdev);\r
794         if (err) {\r
795                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
796                           "memory region table, aborting.\n"));\r
797                 goto err_pd_table_free;\r
798         }\r
799 \r
800         err = mthca_pd_alloc(mdev, 1, &mdev->driver_pd);\r
801         if (err) {\r
802                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to create driver PD, "\r
803                           "aborting.\n"));\r
804                 goto err_mr_table_free;\r
805         }\r
806 \r
807         err = mthca_init_eq_table(mdev);\r
808         if (err) {\r
809                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW, ("Failed to initialize "\r
810                           "event queue table, aborting.\n"));\r
811                 goto err_pd_free;\r
812         }\r
813 \r
814         err = mthca_cmd_use_events(mdev);\r
815         if (err) {\r
816                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to switch to event-driven "\r
817                           "firmware commands, aborting.\n"));\r
818                 goto err_eq_table_free;\r
819         }\r
820 \r
821         err = mthca_NOP(mdev, &status);\r
822         if (err || status) {\r
823                 HCA_PRINT_EV(TRACE_LEVEL_ERROR  ,HCA_DBG_LOW  ,("NOP command failed to generate interrupt, aborting.\n"));\r
824                 if (mdev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)){\r
825                         HCA_PRINT_EV(TRACE_LEVEL_ERROR  ,HCA_DBG_LOW  ,("Try again with MSI/MSI-X disabled.\n"));\r
826                 }else{\r
827                         HCA_PRINT_EV(TRACE_LEVEL_ERROR  ,HCA_DBG_LOW  ,("BIOS or ACPI interrupt routing problem?\n"));\r
828                 }\r
829 \r
830                 goto err_cmd_poll;\r
831         }\r
832 \r
833         HCA_PRINT(TRACE_LEVEL_VERBOSE  ,HCA_DBG_LOW  ,("NOP command IRQ test passed\n"));\r
834 \r
835         err = mthca_init_cq_table(mdev);\r
836         if (err) {\r
837                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
838                           "completion queue table, aborting.\n"));\r
839                 goto err_cmd_poll;\r
840         }\r
841 \r
842         err = mthca_init_srq_table(mdev);\r
843         if (err) {\r
844                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
845                           "shared receive queue table, aborting.\n"));\r
846                 goto err_cq_table_free;\r
847         }\r
848 \r
849         err = mthca_init_qp_table(mdev);\r
850         if (err) {\r
851                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW, ("Failed to initialize "\r
852                           "queue pair table, aborting.\n"));\r
853                 goto err_srq_table_free;\r
854         }\r
855 \r
856         err = mthca_init_av_table(mdev);\r
857         if (err) {\r
858                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
859                           "address vector table, aborting.\n"));\r
860                 goto err_qp_table_free;\r
861         }\r
862 \r
863         err = mthca_init_mcg_table(mdev);\r
864         if (err) {\r
865                 HCA_PRINT_EV(TRACE_LEVEL_ERROR,HCA_DBG_LOW,("Failed to initialize "\r
866                           "multicast group table, aborting.\n"));\r
867                 goto err_av_table_free;\r
868         }\r
869 \r
870         return 0;\r
871 \r
872 err_av_table_free:\r
873         mthca_cleanup_av_table(mdev);\r
874 \r
875 err_qp_table_free:\r
876         mthca_cleanup_qp_table(mdev);\r
877 \r
878 err_srq_table_free:\r
879         mthca_cleanup_srq_table(mdev);\r
880 \r
881 err_cq_table_free:\r
882         mthca_cleanup_cq_table(mdev);\r
883 \r
884 err_cmd_poll:\r
885         mthca_cmd_use_polling(mdev);\r
886 \r
887 err_eq_table_free:\r
888         mthca_cleanup_eq_table(mdev);\r
889 \r
890 err_pd_free:\r
891         mthca_pd_free(mdev, &mdev->driver_pd);\r
892 \r
893 err_mr_table_free:\r
894         mthca_cleanup_mr_table(mdev);\r
895 \r
896 err_pd_table_free:\r
897         mthca_cleanup_pd_table(mdev);\r
898 \r
899 err_kar_unmap:\r
900         iounmap(mdev->kar, mdev->kar_size);\r
901 \r
902 err_uar_free:\r
903         mthca_uar_free(mdev, &mdev->driver_uar);\r
904 \r
905 err_uar_table_free:\r
906         mthca_cleanup_uar_table(mdev);\r
907         return err;\r
908 }\r
909 \r
910 \r
911 static int      mthca_check_fw(struct mthca_dev *mdev, struct pci_device_id *p_id)\r
912 {\r
913         int err = 0;\r
914         \r
915         if (mdev->fw_ver < mthca_hca_table[p_id->driver_data].max_unsupported_fw) {\r
916                 HCA_PRINT_EV(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("HCA FW version %d.%d.%d is not supported. Use %d.%d.%d or higher.\n",\r
917                            (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff,\r
918                            (int) (mdev->fw_ver & 0xffff),\r
919                            (int) (mthca_hca_table[p_id->driver_data].min_supported_fw >> 32),\r
920                            (int) (mthca_hca_table[p_id->driver_data].min_supported_fw >> 16) & 0xffff,\r
921                            (int) (mthca_hca_table[p_id->driver_data].min_supported_fw & 0xffff)));\r
922                 err = -EINVAL;\r
923         }\r
924         else \r
925         if (mdev->fw_ver < mthca_hca_table[p_id->driver_data].min_supported_fw) {\r
926                 HCA_PRINT_EV(TRACE_LEVEL_WARNING ,HCA_DBG_LOW ,\r
927                         ("The HCA FW version is %d.%d.%d, which is not the latest one. \n"\r
928                         "If you meet any issues with the HCA please first try to upgrade the FW to version %d.%d.%d or higher.\n",\r
929                                  (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff,\r
930                                  (int) (mdev->fw_ver & 0xffff),\r
931                                  (int) (mthca_hca_table[p_id->driver_data].min_supported_fw >> 32),\r
932                                  (int) (mthca_hca_table[p_id->driver_data].min_supported_fw >> 16) & 0xffff,\r
933                                  (int) (mthca_hca_table[p_id->driver_data].min_supported_fw & 0xffff)));\r
934         }\r
935         else {\r
936                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_LOW ,("Current HCA FW version is %d.%d.%d. \n",\r
937                                  (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff,\r
938                                  (int) (mdev->fw_ver & 0xffff)));\r
939         }\r
940 \r
941         return err;\r
942 }\r
943 \r
944 NTSTATUS mthca_init_one(hca_dev_ext_t *ext)\r
945 {\r
946         static int mthca_version_printed = 0;\r
947         int err;\r
948         NTSTATUS status;\r
949         struct mthca_dev *mdev;\r
950         struct pci_device_id *p_id;\r
951 \r
952         /* print version */\r
953         if (!mthca_version_printed) {\r
954                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_LOW ,("%s\n", mthca_version));\r
955                 ++mthca_version_printed;\r
956         }\r
957 \r
958         /* find the type of device */\r
959         p_id = mthca_find_pci_dev(\r
960                 (unsigned)ext->hcaConfig.VendorID,\r
961                 (unsigned)ext->hcaConfig.DeviceID);\r
962         if (p_id == NULL) {\r
963                 status = STATUS_NO_SUCH_DEVICE;\r
964                 goto end;\r
965         }\r
966 \r
967         InitializeListHead(&ext->hca.hob.event_list);\r
968         KeInitializeSpinLock(&ext->hca.hob.event_list_lock);\r
969 \r
970 run_as_livefish:\r
971         /* allocate mdev structure */\r
972         mdev = kzalloc(sizeof *mdev, GFP_KERNEL);\r
973         if (!mdev) {\r
974                 // can't use HCA_PRINT_EV here !\r
975                 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,("Device struct alloc failed, "\r
976                         "aborting.\n"));\r
977                 status = STATUS_INSUFFICIENT_RESOURCES;\r
978                 goto end;\r
979         }\r
980          \r
981         /* set some fields */\r
982         mdev->ext = ext;                /* pointer to DEVICE OBJECT extension */\r
983         mdev->hca_type = p_id->driver_data;\r
984         mdev->ib_dev.mdev = mdev;\r
985         if (p_id->driver_data == LIVEFISH)\r
986                 mdev->mthca_flags |= MTHCA_FLAG_LIVEFISH;\r
987         if (mthca_is_livefish(mdev))\r
988                 goto done;\r
989         if (ext->hca_hidden)\r
990                 mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN;\r
991         if (mthca_hca_table[p_id->driver_data].is_memfree)\r
992                 mdev->mthca_flags |= MTHCA_FLAG_MEMFREE;\r
993         if (mthca_hca_table[p_id->driver_data].is_pcie)\r
994                 mdev->mthca_flags |= MTHCA_FLAG_PCIE;\r
995         \r
996 //TODO: after we have a FW, capable of reset, \r
997 // write a routine, that only presses the button\r
998 \r
999         /*\r
1000          * Now reset the HCA before we touch the PCI capabilities or\r
1001          * attempt a firmware command, since a boot ROM may have left\r
1002          * the HCA in an undefined state.\r
1003          */\r
1004         status = hca_reset( mdev->ext->cl_ext.p_self_do, p_id->driver_data == TAVOR );\r
1005         if ( !NT_SUCCESS( status ) ) {\r
1006                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to reset HCA, aborting.\n"));\r
1007                 goto err_free_dev;\r
1008         }\r
1009 \r
1010         if (mthca_cmd_init(mdev)) {\r
1011                 HCA_PRINT_EV(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,("Failed to init command interface, aborting.\n"));\r
1012                 status = STATUS_DEVICE_DATA_ERROR;\r
1013                 goto err_free_dev;\r
1014         }\r
1015 \r
1016         status = mthca_tune_pci(mdev);\r
1017         if ( !NT_SUCCESS( status ) ) {\r
1018                 goto err_cmd;\r
1019         }\r
1020 \r
1021         err = mthca_init_hca(mdev); \r
1022         if (err) {\r
1023                 status = STATUS_UNSUCCESSFUL;\r
1024                 goto err_cmd;\r
1025         }\r
1026 \r
1027         err = mthca_check_fw(mdev, p_id);\r
1028         if (err) {\r
1029                 status = STATUS_UNSUCCESSFUL;\r
1030                 goto err_close;\r
1031         }\r
1032 \r
1033         err = mthca_setup_hca(mdev);\r
1034         if (err) {\r
1035                 status = STATUS_UNSUCCESSFUL;\r
1036                 goto err_close;\r
1037         }\r
1038 \r
1039         err = mthca_register_device(mdev);\r
1040         if (err) {\r
1041                 status = STATUS_UNSUCCESSFUL;\r
1042                 goto err_cleanup;\r
1043         }\r
1044 \r
1045         done:\r
1046         ext->hca.mdev = mdev;\r
1047         mdev->state = MTHCA_DEV_INITIALIZED;\r
1048         return 0;\r
1049 \r
1050 err_cleanup:\r
1051         mthca_cleanup_mcg_table(mdev);\r
1052         mthca_cleanup_av_table(mdev);\r
1053         mthca_cleanup_qp_table(mdev);\r
1054         mthca_cleanup_srq_table(mdev);\r
1055         mthca_cleanup_cq_table(mdev);\r
1056         mthca_cmd_use_polling(mdev);\r
1057         mthca_cleanup_eq_table(mdev);\r
1058 \r
1059         mthca_pd_free(mdev, &mdev->driver_pd);\r
1060 \r
1061         mthca_cleanup_mr_table(mdev);\r
1062         mthca_cleanup_pd_table(mdev);\r
1063         mthca_cleanup_uar_table(mdev);\r
1064 \r
1065 err_close:\r
1066         mthca_close_hca(mdev);\r
1067 \r
1068 err_cmd:\r
1069         mthca_cmd_cleanup(mdev);\r
1070 \r
1071 err_free_dev:\r
1072         kfree(mdev);\r
1073 \r
1074         /* we failed device initialization - try to simulate "livefish" device to facilitate using FW burning tools */\r
1075         {\r
1076                 USHORT dev_id = ext->hcaConfig.DeviceID;\r
1077                 \r
1078                 if (dev_id == PCI_DEVICE_ID_MELLANOX_ARBEL)\r
1079                         dev_id = PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT;\r
1080                 p_id = mthca_find_pci_dev( (unsigned)ext->hcaConfig.VendorID, dev_id + 1 );\r
1081                 if (p_id == NULL) {\r
1082                         status = STATUS_NO_SUCH_DEVICE;\r
1083                         goto end;\r
1084                 }\r
1085                 goto run_as_livefish;\r
1086         }\r
1087         \r
1088 end:\r
1089         return status;\r
1090 }\r
1091 \r
1092 void mthca_remove_one(hca_dev_ext_t *ext)\r
1093 {\r
1094         struct mthca_dev *mdev = ext->hca.mdev;\r
1095         u8 status;\r
1096         int p;\r
1097 \r
1098         ext->hca.mdev = NULL;\r
1099         if (mdev) {\r
1100                 mdev->state = MTHCA_DEV_UNINITIALIZED;\r
1101                 if (mthca_is_livefish(mdev))\r
1102                         goto done;\r
1103                 mthca_unregister_device(mdev);\r
1104 \r
1105                 for (p = 1; p <= mdev->limits.num_ports; ++p)\r
1106                         mthca_CLOSE_IB(mdev, p, &status);\r
1107 \r
1108                 mthca_cleanup_mcg_table(mdev);\r
1109                 mthca_cleanup_av_table(mdev);\r
1110                 mthca_cleanup_qp_table(mdev);\r
1111                 mthca_cleanup_srq_table(mdev);\r
1112                 mthca_cleanup_cq_table(mdev);\r
1113                 mthca_cmd_use_polling(mdev);\r
1114                 mthca_cleanup_eq_table(mdev);\r
1115                 mthca_pd_free(mdev, &mdev->driver_pd);\r
1116                 mthca_cleanup_mr_table(mdev);\r
1117                 mthca_cleanup_pd_table(mdev);\r
1118                 iounmap(mdev->kar, mdev->kar_size);\r
1119                 mthca_uar_free(mdev, &mdev->driver_uar);\r
1120                 mthca_cleanup_uar_table(mdev);\r
1121                 mthca_close_hca(mdev);\r
1122                 mthca_cmd_cleanup(mdev);\r
1123 done:\r
1124                 kfree(mdev);\r
1125         }\r
1126 }\r
1127 \r
1128 \r
1129 \r