tavor.c revision 9517:b4839b0aa7a4
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * tavor.c
29 *    Tavor (InfiniBand) HCA Driver attach/detach Routines
30 *
31 *    Implements all the routines necessary for the attach, setup,
32 *    initialization (and subsequent possible teardown and detach) of the
33 *    Tavor InfiniBand HCA driver.
34 */
35
36#include <sys/types.h>
37#include <sys/file.h>
38#include <sys/open.h>
39#include <sys/conf.h>
40#include <sys/ddi.h>
41#include <sys/sunddi.h>
42#include <sys/modctl.h>
43#include <sys/stat.h>
44#include <sys/pci.h>
45#include <sys/pci_cap.h>
46#include <sys/bitmap.h>
47#include <sys/policy.h>
48
49#include <sys/ib/adapters/tavor/tavor.h>
50#include <sys/pci.h>
51
52/* Tavor HCA State Pointer */
53void *tavor_statep;
54
55/*
56 * The Tavor "userland resource database" is common to instances of the
57 * Tavor HCA driver.  This structure "tavor_userland_rsrc_db" contains all
58 * the necessary information to maintain it.
59 */
60tavor_umap_db_t tavor_userland_rsrc_db;
61
62static int tavor_attach(dev_info_t *, ddi_attach_cmd_t);
63static int tavor_detach(dev_info_t *, ddi_detach_cmd_t);
64static int tavor_open(dev_t *, int, int, cred_t *);
65static int tavor_close(dev_t, int, int, cred_t *);
66static int tavor_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
67static int tavor_drv_init(tavor_state_t *state, dev_info_t *dip, int instance);
68static void tavor_drv_fini(tavor_state_t *state);
69static int tavor_isr_init(tavor_state_t *state);
70static void tavor_isr_fini(tavor_state_t *state);
71static int tavor_hw_init(tavor_state_t *state);
72static void tavor_hw_fini(tavor_state_t *state,
73    tavor_drv_cleanup_level_t cleanup);
74static int tavor_soft_state_init(tavor_state_t *state);
75static void tavor_soft_state_fini(tavor_state_t *state);
76static int tavor_hca_port_init(tavor_state_t *state);
77static int tavor_hca_ports_shutdown(tavor_state_t *state, uint_t num_init);
78static void tavor_hca_config_setup(tavor_state_t *state,
79    tavor_hw_initqueryhca_t *inithca);
80static int tavor_internal_uarpgs_init(tavor_state_t *state);
81static void tavor_internal_uarpgs_fini(tavor_state_t *state);
82static int tavor_special_qp_contexts_reserve(tavor_state_t *state);
83static void tavor_special_qp_contexts_unreserve(tavor_state_t *state);
84static int tavor_sw_reset(tavor_state_t *state);
85static int tavor_mcg_init(tavor_state_t *state);
86static void tavor_mcg_fini(tavor_state_t *state);
87static int tavor_fw_version_check(tavor_state_t *state);
88static void tavor_device_info_report(tavor_state_t *state);
89static void tavor_pci_capability_list(tavor_state_t *state,
90    ddi_acc_handle_t hdl);
91static void tavor_pci_capability_vpd(tavor_state_t *state,
92    ddi_acc_handle_t hdl, uint_t offset);
93static int tavor_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset,
94    uint32_t addr, uint32_t *data);
95static void tavor_pci_capability_pcix(tavor_state_t *state,
96    ddi_acc_handle_t hdl, uint_t offset);
97static int tavor_intr_or_msi_init(tavor_state_t *state);
98static int tavor_add_intrs(tavor_state_t *state, int intr_type);
99static int tavor_intr_or_msi_fini(tavor_state_t *state);
100
101/* X86 fastreboot support */
102static int tavor_intr_disable(tavor_state_t *);
103static int tavor_quiesce(dev_info_t *);
104
105/* Character/Block Operations */
106static struct cb_ops tavor_cb_ops = {
107	tavor_open,		/* open */
108	tavor_close,		/* close */
109	nodev,			/* strategy (block) */
110	nodev,			/* print (block) */
111	nodev,			/* dump (block) */
112	nodev,			/* read */
113	nodev,			/* write */
114	tavor_ioctl,		/* ioctl */
115	tavor_devmap,		/* devmap */
116	NULL,			/* mmap */
117	nodev,			/* segmap */
118	nochpoll,		/* chpoll */
119	ddi_prop_op,		/* prop_op */
120	NULL,			/* streams */
121	D_NEW | D_MP |
122	D_64BIT | D_HOTPLUG |
123	D_DEVMAP,		/* flags */
124	CB_REV			/* rev */
125};
126
127/* Driver Operations */
128static struct dev_ops tavor_ops = {
129	DEVO_REV,		/* struct rev */
130	0,			/* refcnt */
131	tavor_getinfo,		/* getinfo */
132	nulldev,		/* identify */
133	nulldev,		/* probe */
134	tavor_attach,		/* attach */
135	tavor_detach,		/* detach */
136	nodev,			/* reset */
137	&tavor_cb_ops,		/* cb_ops */
138	NULL,			/* bus_ops */
139	nodev,			/* power */
140	tavor_quiesce,		/* devo_quiesce */
141};
142
143/* Module Driver Info */
144static struct modldrv tavor_modldrv = {
145	&mod_driverops,
146	"Tavor InfiniBand HCA Driver",
147	&tavor_ops
148};
149
150/* Module Linkage */
151static struct modlinkage tavor_modlinkage = {
152	MODREV_1,
153	&tavor_modldrv,
154	NULL
155};
156
157/*
158 * This extern refers to the ibc_operations_t function vector that is defined
159 * in the tavor_ci.c file.
160 */
161extern ibc_operations_t	tavor_ibc_ops;
162
163#ifndef NPROBE
164extern int tnf_mod_load(void);
165extern int tnf_mod_unload(struct modlinkage *mlp);
166#endif
167
168
169/*
170 * _init()
171 */
172int
173_init()
174{
175	int	status;
176
177#ifndef NPROBE
178	(void) tnf_mod_load();
179#endif
180	TAVOR_TNF_ENTER(tavor_init);
181
182	status = ddi_soft_state_init(&tavor_statep, sizeof (tavor_state_t),
183	    (size_t)TAVOR_INITIAL_STATES);
184	if (status != 0) {
185		TNF_PROBE_0(tavor_init_ssi_fail, TAVOR_TNF_ERROR, "");
186		TAVOR_TNF_EXIT(tavor_init);
187#ifndef NPROBE
188		(void) tnf_mod_unload(&tavor_modlinkage);
189#endif
190		return (status);
191	}
192
193	status = ibc_init(&tavor_modlinkage);
194	if (status != 0) {
195		TNF_PROBE_0(tavor_init_ibc_init_fail, TAVOR_TNF_ERROR, "");
196		ddi_soft_state_fini(&tavor_statep);
197		TAVOR_TNF_EXIT(tavor_init);
198#ifndef NPROBE
199		(void) tnf_mod_unload(&tavor_modlinkage);
200#endif
201		return (status);
202	}
203	status = mod_install(&tavor_modlinkage);
204	if (status != 0) {
205		TNF_PROBE_0(tavor_init_modi_fail, TAVOR_TNF_ERROR, "");
206		ibc_fini(&tavor_modlinkage);
207		ddi_soft_state_fini(&tavor_statep);
208		TAVOR_TNF_EXIT(tavor_init);
209#ifndef NPROBE
210		(void) tnf_mod_unload(&tavor_modlinkage);
211#endif
212		return (status);
213	}
214
215	/* Initialize the Tavor "userland resources database" */
216	tavor_umap_db_init();
217
218	TAVOR_TNF_EXIT(tavor_init);
219	return (status);
220}
221
222
223/*
224 * _info()
225 */
226int
227_info(struct modinfo *modinfop)
228{
229	int	status;
230
231	TAVOR_TNF_ENTER(tavor_info);
232	status = mod_info(&tavor_modlinkage, modinfop);
233	TAVOR_TNF_EXIT(tavor_info);
234	return (status);
235}
236
237
238/*
239 * _fini()
240 */
241int
242_fini()
243{
244	int	status;
245
246	TAVOR_TNF_ENTER(tavor_fini);
247
248	status = mod_remove(&tavor_modlinkage);
249	if (status != 0) {
250		TNF_PROBE_0(tavor_fini_modr_fail, TAVOR_TNF_ERROR, "");
251		TAVOR_TNF_EXIT(tavor_fini);
252		return (status);
253	}
254
255	/* Destroy the Tavor "userland resources database" */
256	tavor_umap_db_fini();
257
258	ibc_fini(&tavor_modlinkage);
259	ddi_soft_state_fini(&tavor_statep);
260#ifndef NPROBE
261	(void) tnf_mod_unload(&tavor_modlinkage);
262#endif
263	TAVOR_TNF_EXIT(tavor_fini);
264	return (status);
265}
266
267
268/*
269 * tavor_getinfo()
270 */
271/* ARGSUSED */
272static int
273tavor_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
274{
275	dev_t		dev;
276	tavor_state_t 	*state;
277	minor_t		instance;
278
279	TAVOR_TNF_ENTER(tavor_getinfo);
280
281	switch (cmd) {
282	case DDI_INFO_DEVT2DEVINFO:
283		dev = (dev_t)arg;
284		instance = TAVOR_DEV_INSTANCE(dev);
285		state = ddi_get_soft_state(tavor_statep, instance);
286		if (state == NULL) {
287			TNF_PROBE_0(tavor_getinfo_gss_fail,
288			    TAVOR_TNF_ERROR, "");
289			TAVOR_TNF_EXIT(tavor_getinfo);
290			return (DDI_FAILURE);
291		}
292		*result = (void *)state->ts_dip;
293		return (DDI_SUCCESS);
294
295	case DDI_INFO_DEVT2INSTANCE:
296		dev = (dev_t)arg;
297		instance = TAVOR_DEV_INSTANCE(dev);
298		*result = (void *)(uintptr_t)instance;
299		return (DDI_SUCCESS);
300
301	default:
302		TNF_PROBE_0(tavor_getinfo_default_fail, TAVOR_TNF_ERROR, "");
303		break;
304	}
305
306	TAVOR_TNF_EXIT(tavor_getinfo);
307	return (DDI_FAILURE);
308}
309
310
311/*
312 * tavor_open()
313 */
314/* ARGSUSED */
315static int
316tavor_open(dev_t *devp, int flag, int otyp, cred_t *credp)
317{
318	tavor_state_t		*state;
319	tavor_rsrc_t 		*rsrcp;
320	tavor_umap_db_entry_t	*umapdb, *umapdb2;
321	minor_t			instance;
322	uint64_t		key, value;
323	uint_t			tr_indx;
324	dev_t			dev;
325	int			status;
326
327	TAVOR_TNF_ENTER(tavor_open);
328
329	instance = TAVOR_DEV_INSTANCE(*devp);
330	state = ddi_get_soft_state(tavor_statep, instance);
331	if (state == NULL) {
332		TNF_PROBE_0(tavor_open_gss_fail, TAVOR_TNF_ERROR, "");
333		TAVOR_TNF_EXIT(tavor_open);
334		return (ENXIO);
335	}
336
337	/*
338	 * Only allow driver to be opened for character access, and verify
339	 * whether exclusive access is allowed.
340	 */
341	if ((otyp != OTYP_CHR) || ((flag & FEXCL) &&
342	    secpolicy_excl_open(credp) != 0)) {
343		TNF_PROBE_0(tavor_open_invflags_fail, TAVOR_TNF_ERROR, "");
344		TAVOR_TNF_EXIT(tavor_open);
345		return (EINVAL);
346	}
347
348	/*
349	 * Search for the current process PID in the "userland resources
350	 * database".  If it is not found, then attempt to allocate a UAR
351	 * page and add the ("key", "value") pair to the database.
352	 * Note:  As a last step we always return a devp appropriate for
353	 * the open.  Either we return a new minor number (based on the
354	 * instance and the UAR page index) or we return the current minor
355	 * number for the given client process.
356	 *
357	 * We also add an entry to the database to allow for lookup from
358	 * "dev_t" to the current process PID.  This is necessary because,
359	 * under certain circumstance, the process PID that calls the Tavor
360	 * close() entry point may not be the same as the one who called
361	 * open().  Specifically, this can happen if a child process calls
362	 * the Tavor's open() entry point, gets a UAR page, maps it out (using
363	 * mmap()), and then exits without calling munmap().  Because mmap()
364	 * adds a reference to the file descriptor, at the exit of the child
365	 * process the file descriptor is "inherited" by the parent (and will
366	 * be close()'d by the parent's PID only when it exits).
367	 *
368	 * Note: We use the tavor_umap_db_find_nolock() and
369	 * tavor_umap_db_add_nolock() database access routines below (with
370	 * an explicit mutex_enter of the database lock - "tdl_umapdb_lock")
371	 * to ensure that the multiple accesses (in this case searching for,
372	 * and then adding _two_ database entries) can be done atomically.
373	 */
374	key = ddi_get_pid();
375	mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
376	status = tavor_umap_db_find_nolock(instance, key,
377	    MLNX_UMAP_UARPG_RSRC, &value, 0, NULL);
378	if (status != DDI_SUCCESS) {
379		/*
380		 * If we are in 'maintenance mode', we cannot alloc a UAR page.
381		 * But we still need some rsrcp value, and a mostly unique
382		 * tr_indx value.  So we set rsrcp to NULL for maintenance
383		 * mode, and use a rolling count for tr_indx.  The field
384		 * 'ts_open_tr_indx' is used only in this maintenance mode
385		 * condition.
386		 *
387		 * Otherwise, if we are in operational mode then we allocate
388		 * the UAR page as normal, and use the rsrcp value and tr_indx
389		 * value from that allocation.
390		 */
391		if (!TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
392			rsrcp = NULL;
393			tr_indx = state->ts_open_tr_indx++;
394		} else {
395			/* Allocate a new UAR page for this process */
396			status = tavor_rsrc_alloc(state, TAVOR_UARPG, 1,
397			    TAVOR_NOSLEEP, &rsrcp);
398			if (status != DDI_SUCCESS) {
399				mutex_exit(
400				    &tavor_userland_rsrc_db.tdl_umapdb_lock);
401				TNF_PROBE_0(tavor_open_rsrcalloc_uarpg_fail,
402				    TAVOR_TNF_ERROR, "");
403				TAVOR_TNF_EXIT(tavor_open);
404				return (EAGAIN);
405			}
406
407			tr_indx = rsrcp->tr_indx;
408		}
409
410		/*
411		 * Allocate an entry to track the UAR page resource in the
412		 * "userland resources database".
413		 */
414		umapdb = tavor_umap_db_alloc(instance, key,
415		    MLNX_UMAP_UARPG_RSRC, (uint64_t)(uintptr_t)rsrcp);
416		if (umapdb == NULL) {
417			mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
418			/* If in "maintenance mode", don't free the rsrc */
419			if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
420				tavor_rsrc_free(state, &rsrcp);
421			}
422			TNF_PROBE_0(tavor_open_umap_db_alloc_fail,
423			    TAVOR_TNF_ERROR, "");
424			TAVOR_TNF_EXIT(tavor_open);
425			return (EAGAIN);
426		}
427
428		/*
429		 * Create a new device number.  Minor number is a function of
430		 * the UAR page index (15 bits) and the device instance number
431		 * (3 bits).
432		 */
433		dev = makedevice(getmajor(*devp), (tr_indx <<
434		    TAVOR_MINORNUM_SHIFT) | instance);
435
436		/*
437		 * Allocate another entry in the "userland resources database"
438		 * to track the association of the device number (above) to
439		 * the current process ID (in "key").
440		 */
441		umapdb2 = tavor_umap_db_alloc(instance, dev,
442		    MLNX_UMAP_PID_RSRC, (uint64_t)key);
443		if (umapdb2 == NULL) {
444			mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
445			tavor_umap_db_free(umapdb);
446			/* If in "maintenance mode", don't free the rsrc */
447			if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
448				tavor_rsrc_free(state, &rsrcp);
449			}
450			TNF_PROBE_0(tavor_open_umap_db_alloc_fail,
451			    TAVOR_TNF_ERROR, "");
452			TAVOR_TNF_EXIT(tavor_open);
453			return (EAGAIN);
454		}
455
456		/* Add the entries to the database */
457		tavor_umap_db_add_nolock(umapdb);
458		tavor_umap_db_add_nolock(umapdb2);
459
460	} else {
461		/*
462		 * Return the same device number as on the original open()
463		 * call.  This was calculated as a function of the UAR page
464		 * index (top 16 bits) and the device instance number
465		 */
466		rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
467		dev = makedevice(getmajor(*devp), (rsrcp->tr_indx <<
468		    TAVOR_MINORNUM_SHIFT) | instance);
469	}
470	mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
471
472	*devp = dev;
473
474	TAVOR_TNF_EXIT(tavor_open);
475	return (0);
476}
477
478
479/*
480 * tavor_close()
481 */
482/* ARGSUSED */
483static int
484tavor_close(dev_t dev, int flag, int otyp, cred_t *credp)
485{
486	tavor_state_t		*state;
487	tavor_rsrc_t		*rsrcp;
488	tavor_umap_db_entry_t	*umapdb;
489	tavor_umap_db_priv_t	*priv;
490	minor_t			instance;
491	uint64_t		key, value;
492	int			status;
493
494	TAVOR_TNF_ENTER(tavor_close);
495
496	instance = TAVOR_DEV_INSTANCE(dev);
497	state = ddi_get_soft_state(tavor_statep, instance);
498	if (state == NULL) {
499		TNF_PROBE_0(tavor_close_gss_fail, TAVOR_TNF_ERROR, "");
500		TAVOR_TNF_EXIT(tavor_close);
501		return (ENXIO);
502	}
503
504	/*
505	 * Search for "dev_t" in the "userland resources database".  As
506	 * explained above in tavor_open(), we can't depend on using the
507	 * current process ID here to do the lookup because the process
508	 * that ultimately closes may not be the same one who opened
509	 * (because of inheritance).
510	 * So we lookup the "dev_t" (which points to the PID of the process
511	 * that opened), and we remove the entry from the database (and free
512	 * it up).  Then we do another query based on the PID value.  And when
513	 * we find that database entry, we free it up too and then free the
514	 * Tavor UAR page resource.
515	 *
516	 * Note: We use the tavor_umap_db_find_nolock() database access
517	 * routine below (with an explicit mutex_enter of the database lock)
518	 * to ensure that the multiple accesses (which attempt to remove the
519	 * two database entries) can be done atomically.
520	 *
521	 * This works the same in both maintenance mode and HCA mode, except
522	 * for the call to tavor_rsrc_free().  In the case of maintenance mode,
523	 * this call is not needed, as it was not allocated in tavor_open()
524	 * above.
525	 */
526	key = dev;
527	mutex_enter(&tavor_userland_rsrc_db.tdl_umapdb_lock);
528	status = tavor_umap_db_find_nolock(instance, key, MLNX_UMAP_PID_RSRC,
529	    &value, TAVOR_UMAP_DB_REMOVE, &umapdb);
530	if (status == DDI_SUCCESS) {
531		/*
532		 * If the "tdb_priv" field is non-NULL, it indicates that
533		 * some "on close" handling is still necessary.  Call
534		 * tavor_umap_db_handle_onclose_cb() to do the handling (i.e.
535		 * to invoke all the registered callbacks).  Then free up
536		 * the resources associated with "tdb_priv" and continue
537		 * closing.
538		 */
539		priv = (tavor_umap_db_priv_t *)umapdb->tdbe_common.tdb_priv;
540		if (priv != NULL) {
541			tavor_umap_db_handle_onclose_cb(priv);
542			kmem_free(priv, sizeof (tavor_umap_db_priv_t));
543			umapdb->tdbe_common.tdb_priv = (void *)NULL;
544		}
545
546		tavor_umap_db_free(umapdb);
547
548		/*
549		 * Now do another lookup using PID as the key (copy it from
550		 * "value").  When this lookup is complete, the "value" field
551		 * will contain the tavor_rsrc_t pointer for the UAR page
552		 * resource.
553		 */
554		key = value;
555		status = tavor_umap_db_find_nolock(instance, key,
556		    MLNX_UMAP_UARPG_RSRC, &value, TAVOR_UMAP_DB_REMOVE,
557		    &umapdb);
558		if (status == DDI_SUCCESS) {
559			tavor_umap_db_free(umapdb);
560			/* If in "maintenance mode", don't free the rsrc */
561			if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
562				rsrcp = (tavor_rsrc_t *)(uintptr_t)value;
563				tavor_rsrc_free(state, &rsrcp);
564			}
565		}
566	}
567	mutex_exit(&tavor_userland_rsrc_db.tdl_umapdb_lock);
568
569	TAVOR_TNF_EXIT(tavor_close);
570	return (0);
571}
572
573
574/*
575 * tavor_attach()
576 *    Context: Only called from attach() path context
577 */
578static int
579tavor_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
580{
581	tavor_state_t	*state;
582	ibc_clnt_hdl_t	tmp_ibtfpriv;
583	ibc_status_t	ibc_status;
584	int		instance;
585	int		status;
586
587	TAVOR_TNF_ENTER(tavor_attach);
588
589#ifdef __lock_lint
590	(void) tavor_quiesce(dip);
591#endif
592
593	switch (cmd) {
594	case DDI_ATTACH:
595		instance = ddi_get_instance(dip);
596		status = ddi_soft_state_zalloc(tavor_statep, instance);
597		if (status != DDI_SUCCESS) {
598			TNF_PROBE_0(tavor_attach_ssz_fail, TAVOR_TNF_ERROR, "");
599			cmn_err(CE_NOTE, "tavor%d: driver failed to attach: "
600			    "attach_ssz_fail", instance);
601			goto fail_attach_nomsg;
602
603		}
604		state = ddi_get_soft_state(tavor_statep, instance);
605		if (state == NULL) {
606			ddi_soft_state_free(tavor_statep, instance);
607			TNF_PROBE_0(tavor_attach_gss_fail, TAVOR_TNF_ERROR, "");
608			cmn_err(CE_NOTE, "tavor%d: driver failed to attach: "
609			    "attach_gss_fail", instance);
610			goto fail_attach_nomsg;
611		}
612
613		/* clear the attach error buffer */
614		TAVOR_ATTACH_MSG_INIT(state->ts_attach_buf);
615
616		/*
617		 * Initialize Tavor driver and hardware.
618		 *
619		 * Note: If this initialization fails we may still wish to
620		 * create a device node and remain operational so that Tavor
621		 * firmware can be updated/flashed (i.e. "maintenance mode").
622		 * If this is the case, then "ts_operational_mode" will be
623		 * equal to TAVOR_MAINTENANCE_MODE.  We will not attempt to
624		 * attach to the IBTF or register with the IBMF (i.e. no
625		 * InfiniBand interfaces will be enabled).
626		 */
627		status = tavor_drv_init(state, dip, instance);
628		if ((status != DDI_SUCCESS) &&
629		    (TAVOR_IS_OPERATIONAL(state->ts_operational_mode))) {
630			TNF_PROBE_0(tavor_attach_drvinit_fail,
631			    TAVOR_TNF_ERROR, "");
632			goto fail_attach;
633		}
634
635		/* Create the minor node for device */
636		status = ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
637		    DDI_PSEUDO, 0);
638		if (status != DDI_SUCCESS) {
639			tavor_drv_fini(state);
640			TAVOR_ATTACH_MSG(state->ts_attach_buf,
641			    "attach_create_mn_fail");
642			TNF_PROBE_0(tavor_attach_create_mn_fail,
643			    TAVOR_TNF_ERROR, "");
644			goto fail_attach;
645		}
646
647		/*
648		 * If we are in "maintenance mode", then we don't want to
649		 * register with the IBTF.  All InfiniBand interfaces are
650		 * uninitialized, and the device is only capable of handling
651		 * requests to update/flash firmware (or test/debug requests).
652		 */
653		if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
654
655			/* Attach to InfiniBand Transport Framework (IBTF) */
656			ibc_status = ibc_attach(&tmp_ibtfpriv,
657			    &state->ts_ibtfinfo);
658			if (ibc_status != IBC_SUCCESS) {
659				ddi_remove_minor_node(dip, "devctl");
660				tavor_drv_fini(state);
661				TNF_PROBE_0(tavor_attach_ibcattach_fail,
662				    TAVOR_TNF_ERROR, "");
663				TAVOR_ATTACH_MSG(state->ts_attach_buf,
664				    "attach_ibcattach_fail");
665				goto fail_attach;
666			}
667
668			/*
669			 * Now that we've successfully attached to the IBTF,
670			 * we enable all appropriate asynch and CQ events to
671			 * be forwarded to the IBTF.
672			 */
673			TAVOR_ENABLE_IBTF_CALLB(state, tmp_ibtfpriv);
674
675			ibc_post_attach(state->ts_ibtfpriv);
676
677			/* Register agents with IB Mgmt Framework (IBMF) */
678			status = tavor_agent_handlers_init(state);
679			if (status != DDI_SUCCESS) {
680				(void) ibc_pre_detach(tmp_ibtfpriv, DDI_DETACH);
681				TAVOR_QUIESCE_IBTF_CALLB(state);
682				if (state->ts_in_evcallb != 0) {
683					TAVOR_WARNING(state, "unable to "
684					    "quiesce Tavor IBTF callbacks");
685				}
686				ibc_detach(tmp_ibtfpriv);
687				ddi_remove_minor_node(dip, "devctl");
688				tavor_drv_fini(state);
689				TNF_PROBE_0(tavor_attach_agentinit_fail,
690				    TAVOR_TNF_ERROR, "");
691				TAVOR_ATTACH_MSG(state->ts_attach_buf,
692				    "attach_agentinit_fail");
693				goto fail_attach;
694			}
695		}
696
697		/* Report that driver was loaded */
698		ddi_report_dev(dip);
699
700		/* Send device information to log file */
701		tavor_device_info_report(state);
702
703		/* Report attach in maintenance mode, if appropriate */
704		if (!(TAVOR_IS_OPERATIONAL(state->ts_operational_mode))) {
705			cmn_err(CE_NOTE, "tavor%d: driver attached "
706			    "(for maintenance mode only)", state->ts_instance);
707		}
708
709		TAVOR_TNF_EXIT(tavor_attach);
710		return (DDI_SUCCESS);
711
712	case DDI_RESUME:
713		/* Add code here for DDI_RESUME XXX */
714		TAVOR_TNF_EXIT(tavor_attach);
715		return (DDI_FAILURE);
716
717	default:
718		TNF_PROBE_0(tavor_attach_default_fail, TAVOR_TNF_ERROR, "");
719		break;
720	}
721
722fail_attach:
723	cmn_err(CE_NOTE, "tavor%d: driver failed to attach: %s", instance,
724	    state->ts_attach_buf);
725	ddi_soft_state_free(tavor_statep, instance);
726fail_attach_nomsg:
727	TAVOR_TNF_EXIT(tavor_attach);
728	return (DDI_FAILURE);
729}
730
731
732/*
733 * tavor_detach()
734 *    Context: Only called from detach() path context
735 */
736static int
737tavor_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
738{
739	tavor_state_t	*state;
740	ibc_clnt_hdl_t	tmp_ibtfpriv;
741	ibc_status_t	ibc_status;
742	int		instance, status;
743
744	TAVOR_TNF_ENTER(tavor_detach);
745
746	instance = ddi_get_instance(dip);
747	state = ddi_get_soft_state(tavor_statep, instance);
748	if (state == NULL) {
749		TNF_PROBE_0(tavor_detach_gss_fail, TAVOR_TNF_ERROR, "");
750		TAVOR_TNF_EXIT(tavor_detach);
751		return (DDI_FAILURE);
752	}
753
754	switch (cmd) {
755	case DDI_DETACH:
756		/*
757		 * If we are in "maintenance mode", then we do not want to
758		 * do teardown for any of the InfiniBand interfaces.
759		 * Specifically, this means not detaching from IBTF (we never
760		 * attached to begin with) and not deregistering from IBMF.
761		 */
762		if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
763			/* Unregister agents from IB Mgmt Framework (IBMF) */
764			status = tavor_agent_handlers_fini(state);
765			if (status != DDI_SUCCESS) {
766				TNF_PROBE_0(tavor_detach_agentfini_fail,
767				    TAVOR_TNF_ERROR, "");
768				TAVOR_TNF_EXIT(tavor_detach);
769				return (DDI_FAILURE);
770			}
771
772			/*
773			 * Attempt the "pre-detach" from InfiniBand Transport
774			 * Framework (IBTF).  At this point the IBTF is still
775			 * capable of handling incoming asynch and completion
776			 * events.  This "pre-detach" is primarily a mechanism
777			 * to notify the appropriate IBTF clients that the
778			 * HCA is being removed/offlined.
779			 */
780			ibc_status = ibc_pre_detach(state->ts_ibtfpriv, cmd);
781			if (ibc_status != IBC_SUCCESS) {
782				status = tavor_agent_handlers_init(state);
783				if (status != DDI_SUCCESS) {
784					TAVOR_WARNING(state, "failed to "
785					    "restart Tavor agents");
786				}
787				TNF_PROBE_0(tavor_detach_ibcpredetach_fail,
788				    TAVOR_TNF_ERROR, "");
789				TAVOR_TNF_EXIT(tavor_detach);
790				return (DDI_FAILURE);
791			}
792
793			/*
794			 * Before we can fully detach from the IBTF we need to
795			 * ensure that we have handled all outstanding event
796			 * callbacks.  This is accomplished by quiescing the
797			 * event callback mechanism.  Note: if we are unable
798			 * to successfully quiesce the callbacks, then this is
799			 * an indication that something has probably gone
800			 * seriously wrong.  We print out a warning, but
801			 * continue.
802			 */
803			tmp_ibtfpriv = state->ts_ibtfpriv;
804			TAVOR_QUIESCE_IBTF_CALLB(state);
805			if (state->ts_in_evcallb != 0) {
806				TAVOR_WARNING(state, "unable to quiesce Tavor "
807				    "IBTF callbacks");
808			}
809
810			/* Complete the detach from the IBTF */
811			ibc_detach(tmp_ibtfpriv);
812		}
813
814		/* Remove the minor node for device */
815		ddi_remove_minor_node(dip, "devctl");
816
817		/*
818		 * Only call tavor_drv_fini() if we are in Tavor HCA mode.
819		 * (Because if we are in "maintenance mode", then we never
820		 * successfully finished init.)  Only report successful
821		 * detach for normal HCA mode.
822		 */
823		if (TAVOR_IS_OPERATIONAL(state->ts_operational_mode)) {
824			/* Cleanup driver resources and shutdown hardware */
825			tavor_drv_fini(state);
826			cmn_err(CE_CONT, "Tavor driver successfully "
827			    "detached\n");
828		}
829
830		ddi_soft_state_free(tavor_statep, instance);
831
832		TAVOR_TNF_EXIT(tavor_detach);
833		return (DDI_SUCCESS);
834
835	case DDI_SUSPEND:
836		/* Add code here for DDI_SUSPEND XXX */
837		TAVOR_TNF_EXIT(tavor_detach);
838		return (DDI_FAILURE);
839
840	default:
841		TNF_PROBE_0(tavor_detach_default_fail, TAVOR_TNF_ERROR, "");
842		break;
843	}
844
845	TAVOR_TNF_EXIT(tavor_detach);
846	return (DDI_FAILURE);
847}
848
849
850/*
851 * tavor_drv_init()
852 *    Context: Only called from attach() path context
853 */
854static int
855tavor_drv_init(tavor_state_t *state, dev_info_t *dip, int instance)
856{
857	int			status;
858
859	TAVOR_TNF_ENTER(tavor_drv_init);
860
861	/* Save away devinfo and instance */
862	state->ts_dip = dip;
863	state->ts_instance = instance;
864
865	/*
866	 * Check and set the operational mode of the device. If the driver is
867	 * bound to the Tavor device in "maintenance mode", then this generally
868	 * means that either the device has been specifically jumpered to
869	 * start in this mode or the firmware boot process has failed to
870	 * successfully load either the primary or the secondary firmware
871	 * image.
872	 */
873	if (TAVOR_IS_HCA_MODE(state->ts_dip)) {
874		state->ts_operational_mode = TAVOR_HCA_MODE;
875
876	} else if (TAVOR_IS_COMPAT_MODE(state->ts_dip)) {
877		state->ts_operational_mode = TAVOR_COMPAT_MODE;
878
879	} else if (TAVOR_IS_MAINTENANCE_MODE(state->ts_dip)) {
880		state->ts_operational_mode = TAVOR_MAINTENANCE_MODE;
881		return (DDI_FAILURE);
882
883	} else {
884		state->ts_operational_mode = 0;	/* invalid operational mode */
885		TAVOR_WARNING(state, "unexpected device type detected");
886		TNF_PROBE_0(tavor_hw_init_unexpected_dev_fail,
887		    TAVOR_TNF_ERROR, "");
888		TAVOR_TNF_EXIT(tavor_hw_init);
889		return (DDI_FAILURE);
890	}
891
892	/*
893	 * Initialize the Tavor hardware.
894	 *
895	 * Note:  If this routine returns an error, it is often an reasonably
896	 * good indication that something Tavor firmware-related has caused
897	 * the failure.  In order to give the user an opportunity (if desired)
898	 * to update or reflash the Tavor firmware image, we set
899	 * "ts_operational_mode" flag (described above) to indicate that we
900	 * wish to enter maintenance mode.
901	 */
902	status = tavor_hw_init(state);
903	if (status != DDI_SUCCESS) {
904		state->ts_operational_mode = TAVOR_MAINTENANCE_MODE;
905		cmn_err(CE_NOTE, "tavor%d: error during attach: %s", instance,
906		    state->ts_attach_buf);
907		TNF_PROBE_0(tavor_drv_init_hwinit_fail, TAVOR_TNF_ERROR, "");
908		TAVOR_TNF_EXIT(tavor_drv_init);
909		return (DDI_FAILURE);
910	}
911
912	/* Setup Tavor interrupt handler */
913	status = tavor_isr_init(state);
914	if (status != DDI_SUCCESS) {
915		tavor_hw_fini(state, TAVOR_DRV_CLEANUP_ALL);
916		TNF_PROBE_0(tavor_drv_init_isrinit_fail, TAVOR_TNF_ERROR, "");
917		TAVOR_TNF_EXIT(tavor_drv_init);
918		return (DDI_FAILURE);
919	}
920
921	/* Initialize Tavor softstate */
922	status = tavor_soft_state_init(state);
923	if (status != DDI_SUCCESS) {
924		tavor_isr_fini(state);
925		tavor_hw_fini(state, TAVOR_DRV_CLEANUP_ALL);
926		TNF_PROBE_0(tavor_drv_init_ssiinit_fail, TAVOR_TNF_ERROR, "");
927		TAVOR_TNF_EXIT(tavor_drv_init);
928		return (DDI_FAILURE);
929	}
930
931	TAVOR_TNF_EXIT(tavor_drv_init);
932	return (DDI_SUCCESS);
933}
934
935
936/*
937 * tavor_drv_fini()
938 *    Context: Only called from attach() and/or detach() path contexts
939 */
940static void
941tavor_drv_fini(tavor_state_t *state)
942{
943	TAVOR_TNF_ENTER(tavor_drv_fini);
944
945	/* Cleanup Tavor softstate */
946	tavor_soft_state_fini(state);
947
948	/* Teardown Tavor interrupts */
949	tavor_isr_fini(state);
950
951	/* Cleanup Tavor resources and shutdown hardware */
952	tavor_hw_fini(state, TAVOR_DRV_CLEANUP_ALL);
953
954	TAVOR_TNF_EXIT(tavor_drv_fini);
955}
956
957
958/*
959 * tavor_isr_init()
960 *    Context: Only called from attach() path context
961 */
962static int
963tavor_isr_init(tavor_state_t *state)
964{
965	int	status;
966
967	TAVOR_TNF_ENTER(tavor_isr_init);
968
969	/*
970	 * Add a handler for the interrupt or MSI
971	 */
972	status = ddi_intr_add_handler(state->ts_intrmsi_hdl, tavor_isr,
973	    (caddr_t)state, NULL);
974	if (status  != DDI_SUCCESS) {
975		TNF_PROBE_0(tavor_isr_init_addhndlr_fail, TAVOR_TNF_ERROR, "");
976		TAVOR_TNF_EXIT(tavor_isr_init);
977		return (DDI_FAILURE);
978	}
979
980	/*
981	 * Enable the software interrupt.  Note: Even though we are only
982	 * using one (1) interrupt/MSI, depending on the value returned in
983	 * the capability flag, we have to call either ddi_intr_block_enable()
984	 * or ddi_intr_enable().
985	 */
986	if (state->ts_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
987		status = ddi_intr_block_enable(&state->ts_intrmsi_hdl, 1);
988		if (status  != DDI_SUCCESS) {
989			TNF_PROBE_0(tavor_isr_init_blockenable_fail,
990			    TAVOR_TNF_ERROR, "");
991			TAVOR_TNF_EXIT(tavor_isr_init);
992			return (DDI_FAILURE);
993		}
994	} else {
995		status = ddi_intr_enable(state->ts_intrmsi_hdl);
996		if (status  != DDI_SUCCESS) {
997			TNF_PROBE_0(tavor_isr_init_intrenable_fail,
998			    TAVOR_TNF_ERROR, "");
999			TAVOR_TNF_EXIT(tavor_isr_init);
1000			return (DDI_FAILURE);
1001		}
1002	}
1003
1004	/*
1005	 * Now that the ISR has been setup, arm all the EQs for event
1006	 * generation.
1007	 */
1008	tavor_eq_arm_all(state);
1009
1010	TAVOR_TNF_EXIT(tavor_isr_init);
1011	return (DDI_SUCCESS);
1012}
1013
1014
1015/*
1016 * tavor_isr_fini()
1017 *    Context: Only called from attach() and/or detach() path contexts
1018 */
1019static void
1020tavor_isr_fini(tavor_state_t *state)
1021{
1022	TAVOR_TNF_ENTER(tavor_isr_fini);
1023
1024	/* Disable the software interrupt */
1025	if (state->ts_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
1026		(void) ddi_intr_block_disable(&state->ts_intrmsi_hdl, 1);
1027	} else {
1028		(void) ddi_intr_disable(state->ts_intrmsi_hdl);
1029	}
1030
1031	/*
1032	 * Remove the software handler for the interrupt or MSI
1033	 */
1034	(void) ddi_intr_remove_handler(state->ts_intrmsi_hdl);
1035
1036	TAVOR_TNF_EXIT(tavor_isr_fini);
1037}
1038
1039
1040/*
1041 * tavor_fix_error_buf()
1042 *	Context: Only called from attach().
1043 *
1044 * The error_buf_addr returned from QUERY_FW is a PCI address.
1045 * We need to convert it to an offset from the base address,
1046 * which is stored in the assigned-addresses property.
1047 */
1048static int
1049tavor_fix_error_buf(tavor_state_t *state)
1050{
1051	int		assigned_addr_len;
1052	pci_regspec_t	*assigned_addr;
1053
1054	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, state->ts_dip,
1055	    DDI_PROP_DONTPASS, "assigned-addresses", (int **)&assigned_addr,
1056	    (uint_t *)&assigned_addr_len) != DDI_PROP_SUCCESS)
1057		return (DDI_FAILURE);
1058
1059	state->ts_fw.error_buf_addr -= assigned_addr[0].pci_phys_low +
1060	    ((uint64_t)(assigned_addr[0].pci_phys_mid) << 32);
1061	ddi_prop_free(assigned_addr);
1062	return (DDI_SUCCESS);
1063}
1064
1065/*
1066 * tavor_hw_init()
1067 *    Context: Only called from attach() path context
1068 */
1069static int
1070tavor_hw_init(tavor_state_t *state)
1071{
1072	tavor_drv_cleanup_level_t	cleanup;
1073	sm_nodeinfo_t			nodeinfo;
1074	uint64_t			errorcode;
1075	off_t				ddr_size;
1076	int				status;
1077	int				retries;
1078
1079	TAVOR_TNF_ENTER(tavor_hw_init);
1080
1081	/* This is where driver initialization begins */
1082	cleanup = TAVOR_DRV_CLEANUP_LEVEL0;
1083
1084	/* Setup device access attributes */
1085	state->ts_reg_accattr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1086	state->ts_reg_accattr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
1087	state->ts_reg_accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1088
1089	/* Setup for PCI config read/write of HCA device  */
1090	status = pci_config_setup(state->ts_dip, &state->ts_pci_cfghdl);
1091	if (status != DDI_SUCCESS) {
1092		tavor_hw_fini(state, cleanup);
1093		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1094		    "hw_init_PCI_config_space_regmap_fail");
1095		/* This case is not the degraded one */
1096		return (DDI_FAILURE);
1097	}
1098
1099	/* Map in Tavor registers (CMD, UAR, DDR) and setup offsets */
1100	status = ddi_regs_map_setup(state->ts_dip, TAVOR_CMD_BAR,
1101	    &state->ts_reg_cmd_baseaddr, 0, 0, &state->ts_reg_accattr,
1102	    &state->ts_reg_cmdhdl);
1103	if (status != DDI_SUCCESS) {
1104		tavor_hw_fini(state, cleanup);
1105		TNF_PROBE_0(tavor_hw_init_CMD_ddirms_fail, TAVOR_TNF_ERROR, "");
1106		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1107		    "hw_init_CMD_ddirms_fail");
1108		TAVOR_TNF_EXIT(tavor_hw_init);
1109		return (DDI_FAILURE);
1110	}
1111	cleanup = TAVOR_DRV_CLEANUP_LEVEL1;
1112
1113	status = ddi_regs_map_setup(state->ts_dip, TAVOR_UAR_BAR,
1114	    &state->ts_reg_uar_baseaddr, 0, 0, &state->ts_reg_accattr,
1115	    &state->ts_reg_uarhdl);
1116	if (status != DDI_SUCCESS) {
1117		tavor_hw_fini(state, cleanup);
1118		TNF_PROBE_0(tavor_hw_init_UAR_ddirms_fail, TAVOR_TNF_ERROR, "");
1119		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1120		    "hw_init_UAR_ddirms_fail");
1121		TAVOR_TNF_EXIT(tavor_hw_init);
1122		return (DDI_FAILURE);
1123	}
1124	cleanup = TAVOR_DRV_CLEANUP_LEVEL2;
1125
1126	status = ddi_dev_regsize(state->ts_dip, TAVOR_DDR_BAR, &ddr_size);
1127	if (status != DDI_SUCCESS) {
1128		cmn_err(CE_CONT, "Tavor: ddi_dev_regsize() failed "
1129		    "(check HCA-attached DIMM memory?)\n");
1130		tavor_hw_fini(state, cleanup);
1131		TNF_PROBE_0(tavor_hw_init_DDR_ddi_regsize_fail,
1132		    TAVOR_TNF_ERROR, "");
1133		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1134		    "hw_init_DDR_ddi_regsize_fail");
1135		TAVOR_TNF_EXIT(tavor_hw_init);
1136		return (DDI_FAILURE);
1137	}
1138
1139#if !defined(_ELF64) && !defined(__sparc)
1140	/*
1141	 * For 32 bit x86/x64 kernels, where there is limited kernel virtual
1142	 * memory available, define a minimal memory footprint. This is
1143	 * specified in order to not take up too much resources, thus starving
1144	 * out others. Only specified if the HCA DIMM is equal to or greater
1145	 * than 256MB.
1146	 *
1147	 * Note: x86/x64 install and safemode boot are both 32bit.
1148	 */
1149	ddr_size = TAVOR_DDR_SIZE_MIN;
1150#endif	/* !(_ELF64) && !(__sparc) */
1151
1152	state->ts_cfg_profile_setting = ddr_size;
1153
1154	status = ddi_regs_map_setup(state->ts_dip, TAVOR_DDR_BAR,
1155	    &state->ts_reg_ddr_baseaddr, 0, ddr_size, &state->ts_reg_accattr,
1156	    &state->ts_reg_ddrhdl);
1157
1158	/*
1159	 * On 32-bit platform testing (primarily x86), it was seen that the
1160	 * ddi_regs_map_setup() call would fail because there wasn't enough
1161	 * kernel virtual address space available to map in the entire 256MB
1162	 * DDR.  So we add this check in here, so that if the 256 (or other
1163	 * larger value of DDR) map in fails, that we fallback to try the lower
1164	 * size of 128MB.
1165	 *
1166	 * Note: If we only have 128MB of DDR in the system in the first place,
1167	 * we don't try another ddi_regs_map_setup(), and just skip over this
1168	 * check and return failures.
1169	 */
1170	if (status == DDI_ME_NORESOURCES && ddr_size > TAVOR_DDR_SIZE_128) {
1171		/* Try falling back to 128MB DDR mapping */
1172		status = ddi_regs_map_setup(state->ts_dip, TAVOR_DDR_BAR,
1173		    &state->ts_reg_ddr_baseaddr, 0, TAVOR_DDR_SIZE_128,
1174		    &state->ts_reg_accattr, &state->ts_reg_ddrhdl);
1175
1176		/*
1177		 * 128MB DDR mapping worked.
1178		 * Set the updated config profile setting here.
1179		 */
1180		if (status == DDI_SUCCESS) {
1181			TNF_PROBE_0(tavor_hw_init_DDR_128mb_fallback_success,
1182			    TAVOR_TNF_TRACE, "");
1183			state->ts_cfg_profile_setting = TAVOR_DDR_SIZE_128;
1184		}
1185	}
1186
1187	if (status != DDI_SUCCESS) {
1188		if (status == DDI_ME_RNUMBER_RANGE) {
1189			cmn_err(CE_CONT, "Tavor: ddi_regs_map_setup() failed "
1190			    "(check HCA-attached DIMM memory?)\n");
1191		}
1192		tavor_hw_fini(state, cleanup);
1193		TNF_PROBE_0(tavor_hw_init_DDR_ddirms_fail, TAVOR_TNF_ERROR, "");
1194		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1195		    "hw_init_DDR_ddirms_fail");
1196		TAVOR_TNF_EXIT(tavor_hw_init);
1197		return (DDI_FAILURE);
1198	}
1199	cleanup = TAVOR_DRV_CLEANUP_LEVEL3;
1200
1201	/* Setup Tavor Host Command Register (HCR) */
1202	state->ts_cmd_regs.hcr = (tavor_hw_hcr_t *)
1203	    ((uintptr_t)state->ts_reg_cmd_baseaddr + TAVOR_CMD_HCR_OFFSET);
1204
1205	/* Setup Tavor Event Cause Register (ecr and clr_ecr) */
1206	state->ts_cmd_regs.ecr = (uint64_t *)
1207	    ((uintptr_t)state->ts_reg_cmd_baseaddr + TAVOR_CMD_ECR_OFFSET);
1208	state->ts_cmd_regs.clr_ecr = (uint64_t *)
1209	    ((uintptr_t)state->ts_reg_cmd_baseaddr + TAVOR_CMD_CLR_ECR_OFFSET);
1210
1211	/* Setup Tavor Software Reset register (sw_reset) */
1212	state->ts_cmd_regs.sw_reset = (uint32_t *)
1213	    ((uintptr_t)state->ts_reg_cmd_baseaddr + TAVOR_CMD_SW_RESET_OFFSET);
1214
1215	/* Setup Tavor Clear Interrupt register (clr_int) */
1216	state->ts_cmd_regs.clr_int = (uint64_t *)
1217	    ((uintptr_t)state->ts_reg_cmd_baseaddr + TAVOR_CMD_CLR_INT_OFFSET);
1218
1219	/* Initialize the Phase1 Tavor configuration profile */
1220	status = tavor_cfg_profile_init_phase1(state);
1221	if (status != DDI_SUCCESS) {
1222		tavor_hw_fini(state, cleanup);
1223		TNF_PROBE_0(tavor_hw_init_cfginit_fail, TAVOR_TNF_ERROR, "");
1224		TAVOR_ATTACH_MSG(state->ts_attach_buf, "hw_init_cfginit_fail");
1225		TAVOR_TNF_EXIT(tavor_hw_init);
1226		return (DDI_FAILURE);
1227	}
1228	cleanup = TAVOR_DRV_CLEANUP_LEVEL4;
1229
1230	/* Do a software reset of the Tavor HW to ensure proper state */
1231	status = tavor_sw_reset(state);
1232	if (status != TAVOR_CMD_SUCCESS) {
1233		tavor_hw_fini(state, cleanup);
1234		TNF_PROBE_0(tavor_hw_init_sw_reset_fail, TAVOR_TNF_ERROR, "");
1235		TAVOR_ATTACH_MSG(state->ts_attach_buf, "hw_init_sw_reset_fail");
1236		TAVOR_TNF_EXIT(tavor_hw_init);
1237		return (DDI_FAILURE);
1238	}
1239
1240	/* Post the SYS_EN command to start the hardware */
1241	status = tavor_sys_en_cmd_post(state, TAVOR_CMD_SYS_EN_NORMAL,
1242	    &errorcode, TAVOR_CMD_NOSLEEP_SPIN);
1243	if (status != TAVOR_CMD_SUCCESS) {
1244		if ((status == TAVOR_CMD_BAD_NVMEM) ||
1245		    (status == TAVOR_CMD_DDR_MEM_ERR)) {
1246			cmn_err(CE_CONT, "Tavor: SYS_EN command failed: 0x%x "
1247			    "0x%" PRIx64 " (invalid firmware image?)\n",
1248			    status, errorcode);
1249		} else {
1250			cmn_err(CE_CONT, "Tavor: SYS_EN command failed: 0x%x "
1251			    "0x%" PRIx64 "\n", status, errorcode);
1252		}
1253		tavor_hw_fini(state, cleanup);
1254		TNF_PROBE_0(tavor_hw_init_sys_en_cmd_fail,
1255		    TAVOR_TNF_ERROR, "");
1256		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1257		    "hw_init_sys_en_cmd_fail");
1258		TAVOR_TNF_EXIT(tavor_hw_init);
1259		return (DDI_FAILURE);
1260	}
1261	cleanup = TAVOR_DRV_CLEANUP_LEVEL5;
1262
1263	/* First phase of init for Tavor configuration/resources */
1264	status = tavor_rsrc_init_phase1(state);
1265	if (status != DDI_SUCCESS) {
1266		tavor_hw_fini(state, cleanup);
1267		TNF_PROBE_0(tavor_hw_init_rsrcinit1_fail, TAVOR_TNF_ERROR, "");
1268		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1269		    "hw_init_rsrcinit1_fail");
1270		TAVOR_TNF_EXIT(tavor_hw_init);
1271		return (DDI_FAILURE);
1272	}
1273	cleanup = TAVOR_DRV_CLEANUP_LEVEL6;
1274
1275	/* Query the DDR properties (e.g. total DDR size) */
1276	status = tavor_cmn_query_cmd_post(state, QUERY_DDR, 0,
1277	    &state->ts_ddr, sizeof (tavor_hw_queryddr_t),
1278	    TAVOR_CMD_NOSLEEP_SPIN);
1279	if (status != TAVOR_CMD_SUCCESS) {
1280		cmn_err(CE_CONT, "Tavor: QUERY_DDR command failed: %08x\n",
1281		    status);
1282		tavor_hw_fini(state, cleanup);
1283		TNF_PROBE_0(tavor_hw_init_query_ddr_cmd_fail,
1284		    TAVOR_TNF_ERROR, "");
1285		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1286		    "hw_init_query_ddr_cmd_fail");
1287		TAVOR_TNF_EXIT(tavor_hw_init);
1288		return (DDI_FAILURE);
1289	}
1290
1291	/* Figure out how big the firmware image (in DDR) is */
1292	status = tavor_cmn_query_cmd_post(state, QUERY_FW, 0, &state->ts_fw,
1293	    sizeof (tavor_hw_queryfw_t), TAVOR_CMD_NOSLEEP_SPIN);
1294	if (status != TAVOR_CMD_SUCCESS) {
1295		cmn_err(CE_CONT, "Tavor: QUERY_FW command failed: %08x\n",
1296		    status);
1297		tavor_hw_fini(state, cleanup);
1298		TNF_PROBE_0(tavor_hw_init_query_fw_cmd_fail,
1299		    TAVOR_TNF_ERROR, "");
1300		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1301		    "hw_init_query_fw_cmd_fail");
1302		TAVOR_TNF_EXIT(tavor_hw_init);
1303		return (DDI_FAILURE);
1304	}
1305
1306	if (tavor_fix_error_buf(state) != DDI_SUCCESS) {
1307		tavor_hw_fini(state, cleanup);
1308		TNF_PROBE_0(tavor_hw_init_fixerrorbuf_fail,
1309		    TAVOR_TNF_ERROR, "");
1310		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1311		    "hw_init_fixerrorbuf_fail");
1312		TAVOR_TNF_EXIT(tavor_hw_init);
1313		return (DDI_FAILURE);
1314	}
1315
1316	/* Validate that the FW version is appropriate */
1317	status = tavor_fw_version_check(state);
1318	if (status != DDI_SUCCESS) {
1319		if (state->ts_operational_mode == TAVOR_HCA_MODE) {
1320			cmn_err(CE_CONT, "Unsupported Tavor FW version: "
1321			    "expected: %04d.%04d.%04d, "
1322			    "actual: %04d.%04d.%04d\n",
1323			    TAVOR_FW_VER_MAJOR,
1324			    TAVOR_FW_VER_MINOR,
1325			    TAVOR_FW_VER_SUBMINOR,
1326			    state->ts_fw.fw_rev_major,
1327			    state->ts_fw.fw_rev_minor,
1328			    state->ts_fw.fw_rev_subminor);
1329		} else if (state->ts_operational_mode == TAVOR_COMPAT_MODE) {
1330			cmn_err(CE_CONT, "Unsupported Tavor Compat FW version: "
1331			    "expected: %04d.%04d.%04d, "
1332			    "actual: %04d.%04d.%04d\n",
1333			    TAVOR_COMPAT_FW_VER_MAJOR,
1334			    TAVOR_COMPAT_FW_VER_MINOR,
1335			    TAVOR_COMPAT_FW_VER_SUBMINOR,
1336			    state->ts_fw.fw_rev_major,
1337			    state->ts_fw.fw_rev_minor,
1338			    state->ts_fw.fw_rev_subminor);
1339		} else {
1340			cmn_err(CE_CONT, "Unsupported FW version: "
1341			    "%04d.%04d.%04d\n",
1342			    state->ts_fw.fw_rev_major,
1343			    state->ts_fw.fw_rev_minor,
1344			    state->ts_fw.fw_rev_subminor);
1345		}
1346
1347		tavor_hw_fini(state, cleanup);
1348		TNF_PROBE_0(tavor_hw_init_checkfwver_fail,
1349		    TAVOR_TNF_ERROR, "");
1350		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1351		    "hw_init_checkfwver_fail");
1352		TAVOR_TNF_EXIT(tavor_hw_init);
1353		return (DDI_FAILURE);
1354	}
1355
1356	drv_usecwait(10);
1357	retries = 1000;		/* retry up to 1 second before giving up */
1358retry:
1359	/* Call MOD_STAT_CFG to setup SRQ support (or disable) */
1360	status = tavor_mod_stat_cfg_cmd_post(state);
1361	if (status != DDI_SUCCESS) {
1362		if (retries > 0) {
1363			drv_usecwait(1000);
1364			retries--;
1365			goto retry;
1366		}
1367		cmn_err(CE_CONT, "Tavor: MOD_STAT_CFG command failed: %08x\n",
1368		    status);
1369		tavor_hw_fini(state, cleanup);
1370		TNF_PROBE_0(tavor_hw_init_mod_stat_cfg_cmd_fail,
1371		    TAVOR_TNF_ERROR, "");
1372		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1373		    "hw_init_mod_stat_cfg_cmd_fail");
1374		TAVOR_TNF_EXIT(tavor_hw_init);
1375		return (DDI_FAILURE);
1376	}
1377
1378	/* Figure out Tavor device limits */
1379	status = tavor_cmn_query_cmd_post(state, QUERY_DEV_LIM, 0,
1380	    &state->ts_devlim, sizeof (tavor_hw_querydevlim_t),
1381	    TAVOR_CMD_NOSLEEP_SPIN);
1382	if (status != TAVOR_CMD_SUCCESS) {
1383		cmn_err(CE_CONT, "Tavor: QUERY_DEV_LIM command failed: %08x\n",
1384		    status);
1385		tavor_hw_fini(state, cleanup);
1386		TNF_PROBE_0(tavor_hw_init_query_devlim_cmd_fail,
1387		    TAVOR_TNF_ERROR, "");
1388		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1389		    "hw_init_query_devlim_cmd_fail");
1390		TAVOR_TNF_EXIT(tavor_hw_init);
1391		return (DDI_FAILURE);
1392	}
1393
1394	/* Initialize the Phase2 Tavor configuration profile */
1395	status = tavor_cfg_profile_init_phase2(state);
1396	if (status != DDI_SUCCESS) {
1397		tavor_hw_fini(state, cleanup);
1398		TNF_PROBE_0(tavor_hw_init_cfginit2_fail, TAVOR_TNF_ERROR, "");
1399		TAVOR_ATTACH_MSG(state->ts_attach_buf, "hw_init_cfginit2_fail");
1400		TAVOR_TNF_EXIT(tavor_hw_init);
1401		return (DDI_FAILURE);
1402	}
1403
1404	/* Second phase of init for Tavor configuration/resources */
1405	status = tavor_rsrc_init_phase2(state);
1406	if (status != DDI_SUCCESS) {
1407		tavor_hw_fini(state, cleanup);
1408		TNF_PROBE_0(tavor_hw_init_rsrcinit2_fail, TAVOR_TNF_ERROR, "");
1409		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1410		    "hw_init_rsrcinit2_fail");
1411		TAVOR_TNF_EXIT(tavor_hw_init);
1412		return (DDI_FAILURE);
1413	}
1414	cleanup = TAVOR_DRV_CLEANUP_LEVEL7;
1415
1416	/* Miscellaneous query information */
1417	status = tavor_cmn_query_cmd_post(state, QUERY_ADAPTER, 0,
1418	    &state->ts_adapter, sizeof (tavor_hw_queryadapter_t),
1419	    TAVOR_CMD_NOSLEEP_SPIN);
1420	if (status != TAVOR_CMD_SUCCESS) {
1421		cmn_err(CE_CONT, "Tavor: QUERY_ADAPTER command failed: %08x\n",
1422		    status);
1423		tavor_hw_fini(state, cleanup);
1424		TNF_PROBE_0(tavor_hw_init_query_adapter_cmd_fail,
1425		    TAVOR_TNF_ERROR, "");
1426		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1427		    "hw_init_query_adapter_cmd_fail");
1428		TAVOR_TNF_EXIT(tavor_hw_init);
1429		return (DDI_FAILURE);
1430	}
1431
1432	/* Prepare configuration for Tavor INIT_HCA command */
1433	tavor_hca_config_setup(state, &state->ts_hcaparams);
1434
1435	/* Post command to init Tavor HCA */
1436	status = tavor_init_hca_cmd_post(state, &state->ts_hcaparams,
1437	    TAVOR_CMD_NOSLEEP_SPIN);
1438	if (status != TAVOR_CMD_SUCCESS) {
1439		cmn_err(CE_CONT, "Tavor: INIT_HCA command failed: %08x\n",
1440		    status);
1441		tavor_hw_fini(state, cleanup);
1442		TNF_PROBE_0(tavor_hw_init_init_hca_cmd_fail,
1443		    TAVOR_TNF_ERROR, "");
1444		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1445		    "hw_init_init_hca_cmd_fail");
1446		TAVOR_TNF_EXIT(tavor_hw_init);
1447		return (DDI_FAILURE);
1448	}
1449	cleanup = TAVOR_DRV_CLEANUP_LEVEL8;
1450
1451	/* Allocate protection domain (PD) for Tavor internal use */
1452	status = tavor_pd_alloc(state, &state->ts_pdhdl_internal, TAVOR_SLEEP);
1453	if (status != DDI_SUCCESS) {
1454		tavor_hw_fini(state, cleanup);
1455		TNF_PROBE_0(tavor_hw_init_internal_pd_alloc_fail,
1456		    TAVOR_TNF_ERROR, "");
1457		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1458		    "hw_init_internal_pd_alloc_fail");
1459		TAVOR_TNF_EXIT(tavor_hw_init);
1460		return (DDI_FAILURE);
1461	}
1462	cleanup = TAVOR_DRV_CLEANUP_LEVEL9;
1463
1464	/* Setup Tavor internal UAR pages (0 and 1) */
1465	status = tavor_internal_uarpgs_init(state);
1466	if (status != DDI_SUCCESS) {
1467		tavor_hw_fini(state, cleanup);
1468		TNF_PROBE_0(tavor_hw_init_internal_uarpgs_alloc_fail,
1469		    TAVOR_TNF_ERROR, "");
1470		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1471		    "hw_init_internal_uarpgs_alloc_fail");
1472		TAVOR_TNF_EXIT(tavor_hw_init);
1473		return (DDI_FAILURE);
1474	}
1475	cleanup = TAVOR_DRV_CLEANUP_LEVEL10;
1476
1477	/* Query and initialize the Tavor interrupt/MSI information */
1478	status = tavor_intr_or_msi_init(state);
1479	if (status != DDI_SUCCESS) {
1480		tavor_hw_fini(state, cleanup);
1481		TNF_PROBE_0(tavor_intr_or_msi_init_fail,
1482		    TAVOR_TNF_ERROR, "");
1483		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1484		    "intr_or_msi_init_fail");
1485		TAVOR_TNF_EXIT(tavor_hw_init);
1486		return (DDI_FAILURE);
1487	}
1488	cleanup = TAVOR_DRV_CLEANUP_LEVEL11;
1489
1490	/* Setup all of the Tavor EQs */
1491	status = tavor_eq_init_all(state);
1492	if (status != DDI_SUCCESS) {
1493		tavor_hw_fini(state, cleanup);
1494		TNF_PROBE_0(tavor_hw_init_eqinitall_fail, TAVOR_TNF_ERROR, "");
1495		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1496		    "hw_init_eqinitall_fail");
1497		TAVOR_TNF_EXIT(tavor_hw_init);
1498		return (DDI_FAILURE);
1499	}
1500	cleanup = TAVOR_DRV_CLEANUP_LEVEL12;
1501
1502	/* Set aside contexts for QP0 and QP1 */
1503	status = tavor_special_qp_contexts_reserve(state);
1504	if (status != DDI_SUCCESS) {
1505		tavor_hw_fini(state, cleanup);
1506		TNF_PROBE_0(tavor_hw_init_reserve_special_qp_fail,
1507		    TAVOR_TNF_ERROR, "");
1508		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1509		    "hw_init_reserve_special_qp_fail");
1510		TAVOR_TNF_EXIT(tavor_hw_init);
1511		return (DDI_FAILURE);
1512	}
1513	cleanup = TAVOR_DRV_CLEANUP_LEVEL13;
1514
1515	/* Initialize for multicast group handling */
1516	status = tavor_mcg_init(state);
1517	if (status != DDI_SUCCESS) {
1518		tavor_hw_fini(state, cleanup);
1519		TNF_PROBE_0(tavor_hw_init_mcg_init_fail, TAVOR_TNF_ERROR, "");
1520		TAVOR_ATTACH_MSG(state->ts_attach_buf, "hw_init_mcg_init_fail");
1521		TAVOR_TNF_EXIT(tavor_hw_init);
1522		return (DDI_FAILURE);
1523	}
1524	cleanup = TAVOR_DRV_CLEANUP_LEVEL14;
1525
1526	/* Initialize the Tavor IB port(s) */
1527	status = tavor_hca_port_init(state);
1528	if (status != DDI_SUCCESS) {
1529		tavor_hw_fini(state, cleanup);
1530		TNF_PROBE_0(tavor_hw_init_hca_port_init_fail,
1531		    TAVOR_TNF_ERROR, "");
1532		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1533		    "hw_init_hca_port_init_fail");
1534		TAVOR_TNF_EXIT(tavor_hw_init);
1535		return (DDI_FAILURE);
1536	}
1537	cleanup = TAVOR_DRV_CLEANUP_ALL;
1538
1539	/* Determine NodeGUID and SystemImageGUID */
1540	status = tavor_getnodeinfo_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN,
1541	    &nodeinfo);
1542	if (status != TAVOR_CMD_SUCCESS) {
1543		cmn_err(CE_CONT, "Tavor: GetNodeInfo command failed: %08x\n",
1544		    status);
1545		tavor_hw_fini(state, cleanup);
1546		TNF_PROBE_0(tavor_hw_init_getnodeinfo_cmd_fail,
1547		    TAVOR_TNF_ERROR, "");
1548		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1549		    "hw_init_getnodeinfo_cmd_fail");
1550		TAVOR_TNF_EXIT(tavor_hw_init);
1551		return (DDI_FAILURE);
1552	}
1553
1554	/*
1555	 * If the NodeGUID value was set in OBP properties, then we use that
1556	 * value.  But we still print a message if the value we queried from
1557	 * firmware does not match this value.
1558	 *
1559	 * Otherwise if OBP value is not set then we use the value from
1560	 * firmware unconditionally.
1561	 */
1562	if (state->ts_cfg_profile->cp_nodeguid) {
1563		state->ts_nodeguid   = state->ts_cfg_profile->cp_nodeguid;
1564	} else {
1565		state->ts_nodeguid = nodeinfo.NodeGUID;
1566	}
1567
1568	if (state->ts_nodeguid != nodeinfo.NodeGUID) {
1569		cmn_err(CE_NOTE, "!NodeGUID value queried from firmware "
1570		    "does not match value set by device property");
1571	}
1572
1573	/*
1574	 * If the SystemImageGUID value was set in OBP properties, then we use
1575	 * that value.  But we still print a message if the value we queried
1576	 * from firmware does not match this value.
1577	 *
1578	 * Otherwise if OBP value is not set then we use the value from
1579	 * firmware unconditionally.
1580	 */
1581	if (state->ts_cfg_profile->cp_sysimgguid) {
1582		state->ts_sysimgguid = state->ts_cfg_profile->cp_sysimgguid;
1583	} else {
1584		state->ts_sysimgguid = nodeinfo.SystemImageGUID;
1585	}
1586
1587	if (state->ts_sysimgguid != nodeinfo.SystemImageGUID) {
1588		cmn_err(CE_NOTE, "!SystemImageGUID value queried from firmware "
1589		    "does not match value set by device property");
1590	}
1591
1592	/* Get NodeDescription */
1593	status = tavor_getnodedesc_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN,
1594	    (sm_nodedesc_t *)&state->ts_nodedesc);
1595	if (status != TAVOR_CMD_SUCCESS) {
1596		cmn_err(CE_CONT, "Tavor: GetNodeDesc command failed: %08x\n",
1597		    status);
1598		tavor_hw_fini(state, cleanup);
1599		TNF_PROBE_0(tavor_hw_init_getnodedesc_cmd_fail,
1600		    TAVOR_TNF_ERROR, "");
1601		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1602		    "hw_init_getnodedesc_cmd_fail");
1603		TAVOR_TNF_EXIT(tavor_hw_init);
1604		return (DDI_FAILURE);
1605	}
1606
1607	TAVOR_TNF_EXIT(tavor_hw_init);
1608	return (DDI_SUCCESS);
1609}
1610
1611
1612/*
1613 * tavor_hw_fini()
1614 *    Context: Only called from attach() and/or detach() path contexts
1615 */
1616static void
1617tavor_hw_fini(tavor_state_t *state, tavor_drv_cleanup_level_t cleanup)
1618{
1619	uint_t		num_ports;
1620	int		status;
1621
1622	TAVOR_TNF_ENTER(tavor_hw_fini);
1623
1624	switch (cleanup) {
1625	/*
1626	 * If we add more driver initialization steps that should be cleaned
1627	 * up here, we need to ensure that TAVOR_DRV_CLEANUP_ALL is still the
1628	 * first entry (i.e. corresponds to the last init step).
1629	 */
1630	case TAVOR_DRV_CLEANUP_ALL:
1631		/* Shutdown the Tavor IB port(s) */
1632		num_ports = state->ts_cfg_profile->cp_num_ports;
1633		(void) tavor_hca_ports_shutdown(state, num_ports);
1634		/* FALLTHROUGH */
1635
1636	case TAVOR_DRV_CLEANUP_LEVEL14:
1637		/* Teardown resources used for multicast group handling */
1638		tavor_mcg_fini(state);
1639		/* FALLTHROUGH */
1640
1641	case TAVOR_DRV_CLEANUP_LEVEL13:
1642		/* Unreserve the special QP contexts */
1643		tavor_special_qp_contexts_unreserve(state);
1644		/* FALLTHROUGH */
1645
1646	case TAVOR_DRV_CLEANUP_LEVEL12:
1647		/*
1648		 * Attempt to teardown all event queues (EQ).  If we fail
1649		 * here then print a warning message and return.  Something
1650		 * (either in HW or SW) has gone seriously wrong.
1651		 */
1652		status = tavor_eq_fini_all(state);
1653		if (status != DDI_SUCCESS) {
1654			TAVOR_WARNING(state, "failed to teardown EQs");
1655			TNF_PROBE_0(tavor_hw_fini_eqfiniall_fail,
1656			    TAVOR_TNF_ERROR, "");
1657			TAVOR_TNF_EXIT(tavor_hw_fini);
1658			return;
1659		}
1660		/* FALLTHROUGH */
1661
1662	case TAVOR_DRV_CLEANUP_LEVEL11:
1663		status = tavor_intr_or_msi_fini(state);
1664		if (status != DDI_SUCCESS) {
1665			TAVOR_WARNING(state, "failed to free intr/MSI");
1666			TNF_PROBE_0(tavor_hw_fini_intrmsifini_fail,
1667			    TAVOR_TNF_ERROR, "");
1668			TAVOR_TNF_EXIT(tavor_hw_fini);
1669			return;
1670		}
1671		/* FALLTHROUGH */
1672
1673	case TAVOR_DRV_CLEANUP_LEVEL10:
1674		/* Free the resources for the Tavor internal UAR pages */
1675		tavor_internal_uarpgs_fini(state);
1676		/* FALLTHROUGH */
1677
1678	case TAVOR_DRV_CLEANUP_LEVEL9:
1679		/*
1680		 * Free the PD that was used internally by Tavor software.  If
1681		 * we fail here then print a warning and return.  Something
1682		 * (probably software-related, but perhaps HW) has gone wrong.
1683		 */
1684		status = tavor_pd_free(state, &state->ts_pdhdl_internal);
1685		if (status != DDI_SUCCESS) {
1686			TAVOR_WARNING(state, "failed to free internal PD");
1687			TNF_PROBE_0(tavor_hw_fini_internal_pd_free_fail,
1688			    TAVOR_TNF_ERROR, "");
1689			TAVOR_TNF_EXIT(tavor_hw_fini);
1690			return;
1691		}
1692		/* FALLTHROUGH */
1693
1694	case TAVOR_DRV_CLEANUP_LEVEL8:
1695		/*
1696		 * Post the CLOSE_HCA command to Tavor firmware.  If we fail
1697		 * here then print a warning and return.  Something (either in
1698		 * HW or SW) has gone seriously wrong.
1699		 */
1700		status = tavor_close_hca_cmd_post(state,
1701		    TAVOR_CMD_NOSLEEP_SPIN);
1702		if (status != TAVOR_CMD_SUCCESS) {
1703			TAVOR_WARNING(state, "failed to shutdown HCA");
1704			TNF_PROBE_0(tavor_hw_fini_closehcacmd_fail,
1705			    TAVOR_TNF_ERROR, "");
1706			TAVOR_TNF_EXIT(tavor_hw_fini);
1707			return;
1708		}
1709		/* FALLTHROUGH */
1710
1711	case TAVOR_DRV_CLEANUP_LEVEL7:
1712		/* Cleanup all the phase2 resources first */
1713		tavor_rsrc_fini(state, TAVOR_RSRC_CLEANUP_ALL);
1714		/* FALLTHROUGH */
1715
1716	case TAVOR_DRV_CLEANUP_LEVEL6:
1717		/* Then cleanup the phase1 resources */
1718		tavor_rsrc_fini(state, TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE);
1719		/* FALLTHROUGH */
1720
1721	case TAVOR_DRV_CLEANUP_LEVEL5:
1722		/*
1723		 * Post the SYS_DIS command to Tavor firmware to shut
1724		 * everything down again.  If we fail here then print a
1725		 * warning and return.  Something (probably in HW, but maybe
1726		 * in SW) has gone seriously wrong.
1727		 */
1728		status = tavor_sys_dis_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN);
1729		if (status != TAVOR_CMD_SUCCESS) {
1730			TAVOR_WARNING(state, "failed to shutdown hardware");
1731			TNF_PROBE_0(tavor_hw_fini_sys_dis_fail,
1732			    TAVOR_TNF_ERROR, "");
1733			TAVOR_TNF_EXIT(tavor_hw_fini);
1734			return;
1735		}
1736		/* FALLTHROUGH */
1737
1738	case TAVOR_DRV_CLEANUP_LEVEL4:
1739		/* Teardown any resources allocated for the config profile */
1740		tavor_cfg_profile_fini(state);
1741		/* FALLTHROUGH */
1742
1743	case TAVOR_DRV_CLEANUP_LEVEL3:
1744		ddi_regs_map_free(&state->ts_reg_ddrhdl);
1745		/* FALLTHROUGH */
1746
1747	case TAVOR_DRV_CLEANUP_LEVEL2:
1748		ddi_regs_map_free(&state->ts_reg_uarhdl);
1749		/* FALLTHROUGH */
1750
1751	case TAVOR_DRV_CLEANUP_LEVEL1:
1752		ddi_regs_map_free(&state->ts_reg_cmdhdl);
1753		/* FALLTHROUGH */
1754
1755	case TAVOR_DRV_CLEANUP_LEVEL0:
1756		if (state->ts_pci_cfghdl) {
1757			ddi_regs_map_free(&state->ts_pci_cfghdl);
1758			state->ts_pci_cfghdl = NULL;
1759		}
1760		break;
1761
1762	default:
1763		TAVOR_WARNING(state, "unexpected driver cleanup level");
1764		TNF_PROBE_0(tavor_hw_fini_default_fail, TAVOR_TNF_ERROR, "");
1765		TAVOR_TNF_EXIT(tavor_hw_fini);
1766		return;
1767	}
1768
1769	TAVOR_TNF_EXIT(tavor_hw_fini);
1770}
1771
1772
1773/*
1774 * tavor_soft_state_init()
1775 *    Context: Only called from attach() path context
1776 */
1777static int
1778tavor_soft_state_init(tavor_state_t *state)
1779{
1780	ibt_hca_attr_t		*hca_attr;
1781	uint64_t		maxval, val;
1782	ibt_hca_flags_t		caps = IBT_HCA_NO_FLAGS;
1783	int			status;
1784
1785	TAVOR_TNF_ENTER(tavor_soft_state_init);
1786
1787	/*
1788	 * The ibc_hca_info_t struct is passed to the IBTF.  This is the
1789	 * routine where we initialize it.  Many of the init values come from
1790	 * either configuration variables or successful queries of the Tavor
1791	 * hardware abilities
1792	 */
1793	state->ts_ibtfinfo.hca_ci_vers	= IBCI_V3;
1794	state->ts_ibtfinfo.hca_dip	= state->ts_dip;
1795	state->ts_ibtfinfo.hca_handle	= (ibc_hca_hdl_t)state;
1796	state->ts_ibtfinfo.hca_ops	= &tavor_ibc_ops;
1797
1798	hca_attr = kmem_zalloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
1799	state->ts_ibtfinfo.hca_attr = hca_attr;
1800
1801	hca_attr->hca_fw_major_version = state->ts_fw.fw_rev_major;
1802	hca_attr->hca_fw_minor_version = state->ts_fw.fw_rev_minor;
1803	hca_attr->hca_fw_micro_version = state->ts_fw.fw_rev_subminor;
1804
1805	/*
1806	 * Determine HCA capabilities:
1807	 * No default support for IBT_HCA_RD, IBT_HCA_RAW_MULTICAST,
1808	 *    IBT_HCA_ATOMICS_GLOBAL, IBT_HCA_RESIZE_CHAN, IBT_HCA_INIT_TYPE,
1809	 *    or IBT_HCA_SHUTDOWN_PORT
1810	 * But IBT_HCA_AH_PORT_CHECK, IBT_HCA_SQD_RTS_PORT, IBT_HCA_SI_GUID,
1811	 *    IBT_HCA_RNR_NAK, and IBT_HCA_CURRENT_QP_STATE are always
1812	 *    supported
1813	 * All other features are conditionally supported, depending on the
1814	 *    status return by the Tavor HCA (in QUERY_DEV_LIM)
1815	 */
1816	if (state->ts_devlim.ud_multi) {
1817		caps |= IBT_HCA_UD_MULTICAST;
1818	}
1819	if (state->ts_devlim.atomic) {
1820		caps |= IBT_HCA_ATOMICS_HCA;
1821	}
1822	if (state->ts_devlim.apm) {
1823		caps |= IBT_HCA_AUTO_PATH_MIG;
1824	}
1825	if (state->ts_devlim.pkey_v) {
1826		caps |= IBT_HCA_PKEY_CNTR;
1827	}
1828	if (state->ts_devlim.qkey_v) {
1829		caps |= IBT_HCA_QKEY_CNTR;
1830	}
1831	if (state->ts_cfg_profile->cp_srq_enable) {
1832		caps |= IBT_HCA_SRQ | IBT_HCA_RESIZE_SRQ;
1833	}
1834	if (state->ts_cfg_profile->cp_fmr_enable) {
1835		caps |= IBT_HCA_FMR;
1836	}
1837	caps |= (IBT_HCA_AH_PORT_CHECK | IBT_HCA_SQD_SQD_PORT |
1838	    IBT_HCA_SI_GUID | IBT_HCA_RNR_NAK | IBT_HCA_CURRENT_QP_STATE |
1839	    IBT_HCA_PORT_UP | IBT_HCA_SQD_STATE);
1840	hca_attr->hca_flags = caps;
1841
1842	/* Determine VendorID, DeviceID, and revision ID */
1843	hca_attr->hca_vendor_id	 = state->ts_adapter.vendor_id;
1844	hca_attr->hca_device_id	 = state->ts_adapter.device_id;
1845	hca_attr->hca_version_id = state->ts_adapter.rev_id;
1846
1847	/*
1848	 * Determine number of available QPs and max QP size.  Number of
1849	 * available QPs is determined by subtracting the number of
1850	 * "reserved QPs" (i.e. reserved for firmware use) from the
1851	 * total number configured.
1852	 */
1853	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_qp);
1854	hca_attr->hca_max_qp = val - ((uint64_t)1 <<
1855	    state->ts_devlim.log_rsvd_qp);
1856	maxval	= ((uint64_t)1 << state->ts_devlim.log_max_qp_sz);
1857	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_max_qp_sz);
1858	if (val > maxval) {
1859		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1860		TNF_PROBE_2(tavor_soft_state_init_maxqpsz_toobig_fail,
1861		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max QP size "
1862		    "exceeds device maximum", tnf_uint, maxsz, maxval);
1863		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1864		    "soft_state_init_maxqpsz_toobig_fail");
1865		TAVOR_TNF_EXIT(tavor_soft_state_init);
1866		return (DDI_FAILURE);
1867	}
1868	hca_attr->hca_max_qp_sz = val;
1869
1870	/* Determine max scatter-gather size in WQEs */
1871	maxval	= state->ts_devlim.max_sg;
1872	val	= state->ts_cfg_profile->cp_wqe_max_sgl;
1873	if (val > maxval) {
1874		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1875		TNF_PROBE_2(tavor_soft_state_init_toomanysgl_fail,
1876		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of sgl "
1877		    "exceeds device maximum", tnf_uint, maxsgl, maxval);
1878		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1879		    "soft_state_init_toomanysgl_fail");
1880		TAVOR_TNF_EXIT(tavor_soft_state_init);
1881		return (DDI_FAILURE);
1882	}
1883	/* If the rounded value for max SGL is too large, cap it */
1884	if (state->ts_cfg_profile->cp_wqe_real_max_sgl > maxval) {
1885		state->ts_cfg_profile->cp_wqe_real_max_sgl = maxval;
1886		val = maxval;
1887	} else {
1888		val = state->ts_cfg_profile->cp_wqe_real_max_sgl;
1889	}
1890
1891	hca_attr->hca_max_sgl	 = val;
1892	hca_attr->hca_max_rd_sgl = 0;	/* zero because RD is unsupported */
1893
1894	/*
1895	 * Determine number of available CQs and max CQ size. Number of
1896	 * available CQs is determined by subtracting the number of
1897	 * "reserved CQs" (i.e. reserved for firmware use) from the
1898	 * total number configured.
1899	 */
1900	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_cq);
1901	hca_attr->hca_max_cq = val - ((uint64_t)1 <<
1902	    state->ts_devlim.log_rsvd_cq);
1903	maxval	= ((uint64_t)1 << state->ts_devlim.log_max_cq_sz);
1904	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_max_cq_sz) - 1;
1905	if (val > maxval) {
1906		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1907		TNF_PROBE_2(tavor_soft_state_init_maxcqsz_toobig_fail,
1908		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max CQ size "
1909		    "exceeds device maximum", tnf_uint, maxsz, maxval);
1910		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1911		    "soft_state_init_maxcqsz_toobig_fail");
1912		TAVOR_TNF_EXIT(tavor_soft_state_init);
1913		return (DDI_FAILURE);
1914	}
1915	hca_attr->hca_max_cq_sz = val;
1916
1917	/*
1918	 * Determine number of available SRQs and max SRQ size. Number of
1919	 * available SRQs is determined by subtracting the number of
1920	 * "reserved SRQs" (i.e. reserved for firmware use) from the
1921	 * total number configured.
1922	 */
1923	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_srq);
1924	hca_attr->hca_max_srqs = val - ((uint64_t)1 <<
1925	    state->ts_devlim.log_rsvd_srq);
1926	maxval  = ((uint64_t)1 << state->ts_devlim.log_max_srq_sz);
1927	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_max_srq_sz);
1928
1929	if (val > maxval) {
1930		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1931		TNF_PROBE_2(tavor_soft_state_init_maxsrqsz_toobig_fail,
1932		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max SRQ size "
1933		    "exceeds device maximum", tnf_uint, maxsz, maxval);
1934		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1935		    "soft_state_init_maxsrqsz_toobig_fail");
1936		TAVOR_TNF_EXIT(tavor_soft_state_init);
1937		return (DDI_FAILURE);
1938	}
1939	hca_attr->hca_max_srqs_sz = val;
1940
1941	val    = state->ts_cfg_profile->cp_srq_max_sgl;
1942	maxval	= state->ts_devlim.max_sg;
1943	if (val > maxval) {
1944		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1945		TNF_PROBE_2(tavor_soft_state_init_toomanysrqsgl_fail,
1946		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of srq "
1947		    "sgl exceeds device maximum", tnf_uint, maxsgl, maxval);
1948		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1949		    "soft_state_init_toomanysrqsgl_fail");
1950		TAVOR_TNF_EXIT(tavor_soft_state_init);
1951		return (DDI_FAILURE);
1952	}
1953	hca_attr->hca_max_srq_sgl = val;
1954
1955	/*
1956	 * Determine supported HCA page sizes
1957	 * XXX
1958	 * For now we simply return the system pagesize as the only supported
1959	 * pagesize
1960	 */
1961	hca_attr->hca_page_sz = ((PAGESIZE == (1 << 13)) ? IBT_PAGE_8K :
1962	    IBT_PAGE_4K);
1963
1964	/*
1965	 * Determine number of available MemReg, MemWin, and their max size.
1966	 * Number of available MRs and MWs is determined by subtracting
1967	 * the number of "reserved MPTs" (i.e. reserved for firmware use)
1968	 * from the total number configured for each.
1969	 */
1970	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_mpt);
1971	hca_attr->hca_max_memr	  = val - ((uint64_t)1 <<
1972	    state->ts_devlim.log_rsvd_mpt);
1973	hca_attr->hca_max_mem_win = val - ((uint64_t)1 <<
1974	    state->ts_devlim.log_rsvd_mpt);
1975	maxval	= state->ts_devlim.log_max_mrw_sz;
1976	val	= state->ts_cfg_profile->cp_log_max_mrw_sz;
1977	if (val > maxval) {
1978		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1979		TNF_PROBE_2(tavor_soft_state_init_maxmrwsz_toobig_fail,
1980		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max mrw size "
1981		    "exceeds device maximum", tnf_uint, maxsz, maxval);
1982		TAVOR_ATTACH_MSG(state->ts_attach_buf,
1983		    "soft_state_init_maxmrwsz_toobig_fail");
1984		TAVOR_TNF_EXIT(tavor_soft_state_init);
1985		return (DDI_FAILURE);
1986	}
1987	hca_attr->hca_max_memr_len = ((uint64_t)1 << val);
1988
1989	/* Determine RDMA/Atomic properties */
1990	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_rdb);
1991	hca_attr->hca_max_rsc = val;
1992	val = state->ts_cfg_profile->cp_hca_max_rdma_in_qp;
1993	hca_attr->hca_max_rdma_in_qp  = val;
1994	val = state->ts_cfg_profile->cp_hca_max_rdma_out_qp;
1995	hca_attr->hca_max_rdma_out_qp = val;
1996	hca_attr->hca_max_rdma_in_ee  = 0;
1997	hca_attr->hca_max_rdma_out_ee = 0;
1998
1999	/*
2000	 * Determine maximum number of raw IPv6 and Ether QPs.  Set to 0
2001	 * because neither type of raw QP is supported
2002	 */
2003	hca_attr->hca_max_ipv6_qp  = 0;
2004	hca_attr->hca_max_ether_qp = 0;
2005
2006	/* Determine max number of MCGs and max QP-per-MCG */
2007	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_qp);
2008	hca_attr->hca_max_mcg_qps   = val;
2009	val = ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_mcg);
2010	hca_attr->hca_max_mcg	    = val;
2011	val = state->ts_cfg_profile->cp_num_qp_per_mcg;
2012	hca_attr->hca_max_qp_per_mcg = val;
2013
2014	/* Determine max number partitions (i.e. PKeys) */
2015	maxval	= ((uint64_t)1 << state->ts_devlim.log_max_pkey);
2016	val	= ((uint64_t)state->ts_cfg_profile->cp_num_ports <<
2017	    state->ts_cfg_profile->cp_log_max_pkeytbl);
2018
2019	if (val > maxval) {
2020		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2021		TNF_PROBE_2(tavor_soft_state_init_toomanypkey_fail,
2022		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of PKeys "
2023		    "exceeds device maximum", tnf_uint, maxpkey, maxval);
2024		TAVOR_ATTACH_MSG(state->ts_attach_buf,
2025		    "soft_state_init_toomanypkey_fail");
2026		TAVOR_TNF_EXIT(tavor_soft_state_init);
2027		return (DDI_FAILURE);
2028	}
2029	hca_attr->hca_max_partitions = val;
2030
2031	/* Determine number of ports */
2032	maxval = state->ts_devlim.num_ports;
2033	val = state->ts_cfg_profile->cp_num_ports;
2034	if ((val > maxval) || (val == 0)) {
2035		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2036		TNF_PROBE_2(tavor_soft_state_init_toomanyports_fail,
2037		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of ports "
2038		    "exceeds device maximum", tnf_uint, maxports, maxval);
2039		TAVOR_ATTACH_MSG(state->ts_attach_buf,
2040		    "soft_state_init_toomanyports_fail");
2041		TAVOR_TNF_EXIT(tavor_soft_state_init);
2042		return (DDI_FAILURE);
2043	}
2044	hca_attr->hca_nports = val;
2045
2046	/* Copy NodeGUID and SystemImageGUID from softstate */
2047	hca_attr->hca_node_guid = state->ts_nodeguid;
2048	hca_attr->hca_si_guid	= state->ts_sysimgguid;
2049
2050	/*
2051	 * Determine local ACK delay.  Use the value suggested by the Tavor
2052	 * hardware (from the QUERY_DEV_LIM command)
2053	 */
2054	hca_attr->hca_local_ack_delay = state->ts_devlim.ca_ack_delay;
2055
2056	/* Determine max SGID table and PKey table sizes */
2057	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_max_gidtbl);
2058	hca_attr->hca_max_port_sgid_tbl_sz = val;
2059	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_max_pkeytbl);
2060	hca_attr->hca_max_port_pkey_tbl_sz = val;
2061
2062	/* Determine max number of PDs */
2063	maxval	= ((uint64_t)1 << state->ts_devlim.log_max_pd);
2064	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_pd);
2065	if (val > maxval) {
2066		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2067		TNF_PROBE_2(tavor_soft_state_init_toomanypd_fail,
2068		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of PD "
2069		    "exceeds device maximum", tnf_uint, maxpd, maxval);
2070		TAVOR_ATTACH_MSG(state->ts_attach_buf,
2071		    "soft_state_init_toomanypd_fail");
2072		TAVOR_TNF_EXIT(tavor_soft_state_init);
2073		return (DDI_FAILURE);
2074	}
2075	hca_attr->hca_max_pd = val;
2076
2077	/* Determine max number of Address Handles */
2078	maxval	= ((uint64_t)1 << state->ts_devlim.log_max_av);
2079	val	= ((uint64_t)1 << state->ts_cfg_profile->cp_log_num_ah);
2080	if (val > maxval) {
2081		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2082		TNF_PROBE_2(tavor_soft_state_init_toomanyah_fail,
2083		    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of AH "
2084		    "exceeds device maximum", tnf_uint, maxah, maxval);
2085		TAVOR_ATTACH_MSG(state->ts_attach_buf,
2086		    "soft_state_init_toomanyah_fail");
2087		TAVOR_TNF_EXIT(tavor_soft_state_init);
2088		return (DDI_FAILURE);
2089	}
2090	hca_attr->hca_max_ah = val;
2091
2092	/* No RDDs or EECs (since Reliable Datagram is not supported) */
2093	hca_attr->hca_max_rdd = 0;
2094	hca_attr->hca_max_eec = 0;
2095
2096	/* Initialize lock for reserved UAR page access */
2097	mutex_init(&state->ts_uar_lock, NULL, MUTEX_DRIVER,
2098	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2099
2100	/* Initialize the flash fields */
2101	state->ts_fw_flashstarted = 0;
2102	mutex_init(&state->ts_fw_flashlock, NULL, MUTEX_DRIVER,
2103	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2104
2105	/* Initialize the lock for the info ioctl */
2106	mutex_init(&state->ts_info_lock, NULL, MUTEX_DRIVER,
2107	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2108
2109	/* Initialize the AVL tree for QP number support */
2110	tavor_qpn_avl_init(state);
2111
2112	/* Initialize the kstat info structure */
2113	status = tavor_kstat_init(state);
2114	if (status != DDI_SUCCESS) {
2115		tavor_qpn_avl_fini(state);
2116		mutex_destroy(&state->ts_info_lock);
2117		mutex_destroy(&state->ts_fw_flashlock);
2118		mutex_destroy(&state->ts_uar_lock);
2119		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2120		TNF_PROBE_0(tavor_soft_state_init_kstatinit_fail,
2121		    TAVOR_TNF_ERROR, "");
2122		TAVOR_ATTACH_MSG(state->ts_attach_buf,
2123		    "soft_state_init_kstatinit_fail");
2124		TAVOR_TNF_EXIT(tavor_soft_state_init);
2125		return (DDI_FAILURE);
2126	}
2127
2128	TAVOR_TNF_EXIT(tavor_soft_state_init);
2129	return (DDI_SUCCESS);
2130}
2131
2132
2133/*
2134 * tavor_soft_state_fini()
2135 *    Context: Called only from detach() path context
2136 */
2137static void
2138tavor_soft_state_fini(tavor_state_t *state)
2139{
2140	TAVOR_TNF_ENTER(tavor_soft_state_fini);
2141
2142	/* Teardown the kstat info */
2143	tavor_kstat_fini(state);
2144
2145	/* Teardown the AVL tree for QP number support */
2146	tavor_qpn_avl_fini(state);
2147
2148	/* Free up info ioctl mutex */
2149	mutex_destroy(&state->ts_info_lock);
2150
2151	/* Free up flash mutex */
2152	mutex_destroy(&state->ts_fw_flashlock);
2153
2154	/* Free up the UAR page access mutex */
2155	mutex_destroy(&state->ts_uar_lock);
2156
2157	/* Free up the hca_attr struct */
2158	kmem_free(state->ts_ibtfinfo.hca_attr, sizeof (ibt_hca_attr_t));
2159
2160	TAVOR_TNF_EXIT(tavor_soft_state_fini);
2161}
2162
2163
2164/*
2165 * tavor_hca_config_setup()
2166 *    Context: Only called from attach() path context
2167 */
2168static void
2169tavor_hca_config_setup(tavor_state_t *state,
2170    tavor_hw_initqueryhca_t *inithca)
2171{
2172	tavor_rsrc_pool_info_t	*rsrc_pool;
2173	uint64_t		ddr_baseaddr, ddr_base_map_addr;
2174	uint64_t		offset, addr;
2175	uint_t			mcg_size;
2176
2177	TAVOR_TNF_ENTER(tavor_hca_config_setup);
2178
2179	/* Set "host endianness".  Default is big endian */
2180#ifdef	_LITTLE_ENDIAN
2181	inithca->big_endian	= 0;
2182#else
2183	inithca->big_endian	= 1;
2184#endif
2185	/* No Address Vector Protection, but Port Checking on by default */
2186	inithca->udav_chk	= TAVOR_UDAV_PROTECT_DISABLED;
2187	inithca->udav_port_chk	= TAVOR_UDAV_PORTCHK_ENABLED;
2188
2189	ddr_baseaddr	  = (uint64_t)(uintptr_t)state->ts_reg_ddr_baseaddr;
2190	ddr_base_map_addr = (uint64_t)state->ts_ddr.ddr_baseaddr;
2191
2192	/* Setup QPC table */
2193	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPC];
2194	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2195	addr = ddr_base_map_addr + offset;
2196	inithca->context.qpc_baseaddr_h = (addr >> 32);
2197	inithca->context.qpc_baseaddr_l = (addr & 0xFFFFFFFF) >> 7;
2198	inithca->context.log_num_qp	= state->ts_cfg_profile->cp_log_num_qp;
2199
2200	/* Setup EEC table (initialize to zero - RD unsupported) */
2201	inithca->context.eec_baseaddr_h	= 0;
2202	inithca->context.eec_baseaddr_l	= 0;
2203	inithca->context.log_num_ee	= 0;
2204
2205	/* Setup CQC table */
2206	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQC];
2207	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2208	addr = ddr_base_map_addr + offset;
2209	inithca->context.cqc_baseaddr_h = (addr >> 32);
2210	inithca->context.cqc_baseaddr_l = (addr & 0xFFFFFFFF) >> 6;
2211	inithca->context.log_num_cq	= state->ts_cfg_profile->cp_log_num_cq;
2212
2213	/* Setup SRQC table */
2214	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQC];
2215	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2216	addr = ddr_base_map_addr + offset;
2217	inithca->context.srqc_baseaddr_h = (addr >> 32);
2218	inithca->context.srqc_baseaddr_l = (addr & 0xFFFFFFFF) >> 6;
2219	inithca->context.log_num_srq	 =
2220	    state->ts_cfg_profile->cp_log_num_srq;
2221
2222	/* Setup EQPC table */
2223	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQPC];
2224	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2225	addr = ddr_base_map_addr + offset;
2226	inithca->context.eqpc_baseaddr	= addr;
2227
2228	/* Setup EEEC table (initialize to zero - RD unsupported) */
2229	inithca->context.eeec_baseaddr	= 0;
2230
2231	/* Setup EQC table */
2232	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQC];
2233	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2234	addr = ddr_base_map_addr + offset;
2235	inithca->context.eqc_baseaddr_h = (addr >> 32);
2236	inithca->context.eqc_baseaddr_l = (addr & 0xFFFFFFFF) >> 6;
2237	inithca->context.log_num_eq	= TAVOR_NUM_EQ_SHIFT;
2238
2239	/* Setup RDB table */
2240	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_RDB];
2241	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2242	addr = ddr_base_map_addr + offset;
2243	inithca->context.rdb_baseaddr_h	= (addr >> 32);
2244	inithca->context.rdb_baseaddr_l = 0;
2245
2246	/* Setup Multicast */
2247	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MCG];
2248	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2249	addr = ddr_base_map_addr + offset;
2250	inithca->multi.mc_baseaddr	= addr;
2251	mcg_size = TAVOR_MCGMEM_SZ(state);
2252	inithca->multi.log_mc_tbl_ent	= highbit(mcg_size) - 1;
2253	inithca->multi.mc_tbl_hash_sz	=
2254	    (1 << state->ts_cfg_profile->cp_log_num_mcg_hash);
2255	inithca->multi.mc_hash_fn	= TAVOR_MCG_DEFAULT_HASH_FN;
2256	inithca->multi.log_mc_tbl_sz	= state->ts_cfg_profile->cp_log_num_mcg;
2257
2258
2259	/* Setup TPT */
2260	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MPT];
2261	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2262	addr = ddr_base_map_addr + offset;
2263	inithca->tpt.mpt_baseaddr	= addr;
2264	inithca->tpt.mttseg_sz		= TAVOR_MTTSEG_SIZE_SHIFT;
2265	inithca->tpt.log_mpt_sz		= state->ts_cfg_profile->cp_log_num_mpt;
2266	inithca->tpt.mtt_version	= TAVOR_MTT_PG_WALK_VER;
2267
2268	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT];
2269	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2270	addr = ddr_base_map_addr + offset;
2271	inithca->tpt.mtt_baseaddr	= addr;
2272
2273	/* Setup UAR */
2274	rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
2275	offset = (uint64_t)(uintptr_t)rsrc_pool->rsrc_start - ddr_baseaddr;
2276	addr = ddr_base_map_addr + offset;
2277	inithca->uar.uarscr_baseaddr	= addr;
2278
2279	inithca->uar.uar_pg_sz = PAGESHIFT - 0xC;
2280
2281	TAVOR_TNF_EXIT(tavor_hca_config_setup);
2282}
2283
2284
2285/*
2286 * tavor_hca_port_init()
2287 *    Context: Only called from attach() path context
2288 */
2289static int
2290tavor_hca_port_init(tavor_state_t *state)
2291{
2292	tavor_hw_initib_t	*portinits, *initib;
2293	tavor_cfg_profile_t	*cfgprof;
2294	uint_t			num_ports;
2295	int			i, status;
2296	uint64_t		maxval, val;
2297	uint64_t		sysimgguid, nodeguid, portguid;
2298
2299	TAVOR_TNF_ENTER(tavor_hca_port_init);
2300
2301	cfgprof = state->ts_cfg_profile;
2302
2303	/* Get number of HCA ports */
2304	num_ports = cfgprof->cp_num_ports;
2305
2306	/* Allocate space for Tavor port init struct(s) */
2307	portinits = (tavor_hw_initib_t *)kmem_zalloc(num_ports *
2308	    sizeof (tavor_hw_initib_t), KM_SLEEP);
2309
2310	/* Post command to initialize Tavor HCA port */
2311	for (i = 0; i < num_ports; i++) {
2312		initib = &portinits[i];
2313
2314		/*
2315		 * Determine whether we need to override the firmware's
2316		 * default SystemImageGUID setting.
2317		 */
2318		sysimgguid = cfgprof->cp_sysimgguid;
2319		if (sysimgguid != 0) {
2320			initib->set_sysimg_guid	= 1;
2321			initib->sysimg_guid	= sysimgguid;
2322		}
2323
2324		/*
2325		 * Determine whether we need to override the firmware's
2326		 * default NodeGUID setting.
2327		 */
2328		nodeguid = cfgprof->cp_nodeguid;
2329		if (nodeguid != 0) {
2330			initib->set_node_guid	= 1;
2331			initib->node_guid	= nodeguid;
2332		}
2333
2334		/*
2335		 * Determine whether we need to override the firmware's
2336		 * default PortGUID setting.
2337		 */
2338		portguid = cfgprof->cp_portguid[i];
2339		if (portguid != 0) {
2340			initib->set_port_guid0	= 1;
2341			initib->guid0		= portguid;
2342		}
2343
2344		/* Validate max MTU size */
2345		maxval  = state->ts_devlim.max_mtu;
2346		val	= cfgprof->cp_max_mtu;
2347		if (val > maxval) {
2348			TNF_PROBE_2(tavor_hca_port_init_maxmtu_fail,
2349			    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max "
2350			    "MTU size exceeds device maximum", tnf_uint,
2351			    maxmtu, maxval);
2352			TAVOR_TNF_EXIT(tavor_hca_port_init);
2353			goto init_ports_fail;
2354		}
2355		initib->mtu_cap = val;
2356
2357		/* Validate the max port width */
2358		maxval  = state->ts_devlim.max_port_width;
2359		val	= cfgprof->cp_max_port_width;
2360		if (val > maxval) {
2361			TNF_PROBE_2(tavor_hca_port_init_maxportwidth_fail,
2362			    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max "
2363			    "port width exceeds device maximum", tnf_uint,
2364			    maxportwidth, maxval);
2365			TAVOR_TNF_EXIT(tavor_hca_port_init);
2366			goto init_ports_fail;
2367		}
2368		initib->port_width_cap = val;
2369
2370		/* Validate max VL cap size */
2371		maxval  = state->ts_devlim.max_vl;
2372		val	= cfgprof->cp_max_vlcap;
2373		if (val > maxval) {
2374			TNF_PROBE_2(tavor_hca_port_init_maxvlcap_fail,
2375			    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max "
2376			    "VLcap size exceeds device maximum", tnf_uint,
2377			    maxvlcap, maxval);
2378			TAVOR_TNF_EXIT(tavor_hca_port_init);
2379			goto init_ports_fail;
2380		}
2381		initib->vl_cap = val;
2382
2383		/* Validate max GID table size */
2384		maxval  = ((uint64_t)1 << state->ts_devlim.log_max_gid);
2385		val	= ((uint64_t)1 << cfgprof->cp_log_max_gidtbl);
2386		if (val > maxval) {
2387			TNF_PROBE_2(tavor_hca_port_init_gidtable_fail,
2388			    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max "
2389			    "GID table size exceeds device maximum", tnf_uint,
2390			    maxgidtbl, maxval);
2391			TAVOR_TNF_EXIT(tavor_hca_port_init);
2392			goto init_ports_fail;
2393		}
2394		initib->max_gid = val;
2395
2396		/* Validate max PKey table size */
2397		maxval	= ((uint64_t)1 << state->ts_devlim.log_max_pkey);
2398		val	= ((uint64_t)1 << cfgprof->cp_log_max_pkeytbl);
2399		if (val > maxval) {
2400			TNF_PROBE_2(tavor_hca_port_init_pkeytable_fail,
2401			    TAVOR_TNF_ERROR, "", tnf_string, errmsg, "max "
2402			    "PKey table size exceeds device maximum", tnf_uint,
2403			    maxpkeytbl, maxval);
2404			TAVOR_TNF_EXIT(tavor_hca_port_init);
2405			goto init_ports_fail;
2406		}
2407		initib->max_pkey = val;
2408
2409		/*
2410		 * Post the INIT_IB command to Tavor firmware.  When this
2411		 * command completes, the corresponding Tavor port will be
2412		 * physically "Up" and initialized.
2413		 */
2414		status = tavor_init_ib_cmd_post(state, initib, i + 1,
2415		    TAVOR_CMD_NOSLEEP_SPIN);
2416		if (status != TAVOR_CMD_SUCCESS) {
2417			cmn_err(CE_CONT, "Tavor: INIT_IB (port %02d) command "
2418			    "failed: %08x\n", i + 1, status);
2419			TNF_PROBE_2(tavor_hca_port_init_init_ib_cmd_fail,
2420			    TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
2421			    tnf_uint, port, i + 1);
2422			TAVOR_TNF_EXIT(tavor_hca_port_init);
2423			goto init_ports_fail;
2424		}
2425	}
2426
2427	/* Free up the memory for Tavor port init struct(s), return success */
2428	kmem_free(portinits, num_ports * sizeof (tavor_hw_initib_t));
2429	TAVOR_TNF_EXIT(tavor_hca_port_init);
2430	return (DDI_SUCCESS);
2431
2432init_ports_fail:
2433	/*
2434	 * Free up the memory for Tavor port init struct(s), shutdown any
2435	 * successfully initialized ports, and return failure
2436	 */
2437	kmem_free(portinits, num_ports * sizeof (tavor_hw_initib_t));
2438	(void) tavor_hca_ports_shutdown(state, i);
2439
2440	TAVOR_TNF_EXIT(tavor_hca_port_init);
2441	return (DDI_FAILURE);
2442}
2443
2444
2445/*
2446 * tavor_hca_ports_shutdown()
2447 *    Context: Only called from attach() and/or detach() path contexts
2448 */
2449static int
2450tavor_hca_ports_shutdown(tavor_state_t *state, uint_t num_init)
2451{
2452	int	i, status;
2453
2454	TAVOR_TNF_ENTER(tavor_hca_ports_shutdown);
2455
2456	/*
2457	 * Post commands to shutdown all init'd Tavor HCA ports.  Note: if
2458	 * any of these commands fail for any reason, it would be entirely
2459	 * unexpected and probably indicative a serious problem (HW or SW).
2460	 * Although we do return void from this function, this type of failure
2461	 * should not go unreported.  That is why we have the warning message
2462	 * and the detailed TNF information.
2463	 */
2464	for (i = 0; i < num_init; i++) {
2465		status = tavor_close_ib_cmd_post(state, i + 1,
2466		    TAVOR_CMD_NOSLEEP_SPIN);
2467		if (status != TAVOR_CMD_SUCCESS) {
2468			TAVOR_WARNING(state, "failed to shutdown HCA port");
2469			TNF_PROBE_2(tavor_hca_ports_shutdown_close_ib_cmd_fail,
2470			    TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
2471			    tnf_uint, port, i + 1);
2472			TAVOR_TNF_EXIT(tavor_hca_ports_shutdown);
2473			return (status);
2474		}
2475	}
2476
2477	TAVOR_TNF_EXIT(tavor_hca_ports_shutdown);
2478
2479	return (TAVOR_CMD_SUCCESS);
2480}
2481
2482
2483/*
2484 * tavor_internal_uarpgs_init
2485 *    Context: Only called from attach() path context
2486 */
2487static int
2488tavor_internal_uarpgs_init(tavor_state_t *state)
2489{
2490	int	status;
2491
2492	TAVOR_TNF_ENTER(tavor_internal_uarpgs_init);
2493
2494	/*
2495	 * Save away reserved Tavor UAR page #0.  This UAR page is not to
2496	 * be used by software.
2497	 */
2498	status = tavor_rsrc_alloc(state, TAVOR_UARPG, 1, TAVOR_SLEEP,
2499	    &state->ts_uarpg0_rsrc_rsrvd);
2500	if (status != DDI_SUCCESS) {
2501		TNF_PROBE_0(tavor_uarpg0_rsrcalloc_fail, TAVOR_TNF_ERROR, "");
2502		TAVOR_TNF_EXIT(tavor_internal_uarpgs_init);
2503		return (DDI_FAILURE);
2504	}
2505
2506	/*
2507	 * Save away Tavor UAR page #1 (for internal use).  This UAR page is
2508	 * the privileged UAR page through which all kernel generated
2509	 * doorbells will be rung.
2510	 */
2511	status = tavor_rsrc_alloc(state, TAVOR_UARPG, 1, TAVOR_SLEEP,
2512	    &state->ts_uarpg1_rsrc);
2513	if (status != DDI_SUCCESS) {
2514		tavor_rsrc_free(state, &state->ts_uarpg0_rsrc_rsrvd);
2515		TNF_PROBE_0(tavor_uarpg1_rsrcalloc_fail, TAVOR_TNF_ERROR, "");
2516		TAVOR_TNF_EXIT(tavor_internal_uarpgs_init);
2517		return (DDI_FAILURE);
2518	}
2519
2520	/* Setup pointer to UAR page #1 doorbells */
2521	state->ts_uar = (tavor_hw_uar_t *)state->ts_uarpg1_rsrc->tr_addr;
2522
2523	TAVOR_TNF_EXIT(tavor_internal_uarpgs_init);
2524	return (DDI_SUCCESS);
2525}
2526
2527
2528/*
2529 * tavor_internal_uarpgs_fini
2530 *    Context: Only called from attach() and/or detach() path contexts
2531 */
2532static void
2533tavor_internal_uarpgs_fini(tavor_state_t *state)
2534{
2535	TAVOR_TNF_ENTER(tavor_internal_uarpgs_fini);
2536
2537	/* Free up Tavor UAR page #1 (kernel driver doorbells) */
2538	tavor_rsrc_free(state, &state->ts_uarpg1_rsrc);
2539
2540	/* Free up Tavor UAR page #0 (reserved) */
2541	tavor_rsrc_free(state, &state->ts_uarpg0_rsrc_rsrvd);
2542
2543	TAVOR_TNF_EXIT(tavor_internal_uarpgs_fini);
2544}
2545
2546
2547/*
2548 * tavor_special_qp_contexts_reserve()
2549 *    Context: Only called from attach() path context
2550 */
2551static int
2552tavor_special_qp_contexts_reserve(tavor_state_t *state)
2553{
2554	tavor_rsrc_t	*qp0_rsrc, *qp1_rsrc;
2555	int		status;
2556
2557	TAVOR_TNF_ENTER(tavor_special_qp_contexts_reserve);
2558
2559	/* Initialize the lock used for special QP rsrc management */
2560	mutex_init(&state->ts_spec_qplock, NULL, MUTEX_DRIVER,
2561	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2562
2563	/*
2564	 * Reserve contexts for QP0.  These QP contexts will be setup to
2565	 * act as aliases for the real QP0.  Note: We are required to grab
2566	 * two QPs (one per port) even if we are operating in single-port
2567	 * mode.
2568	 */
2569	status = tavor_rsrc_alloc(state, TAVOR_QPC, 2, TAVOR_SLEEP, &qp0_rsrc);
2570	if (status != DDI_SUCCESS) {
2571		mutex_destroy(&state->ts_spec_qplock);
2572		TNF_PROBE_0(tavor_special_qp_contexts_reserve_qp0_fail,
2573		    TAVOR_TNF_ERROR, "");
2574		TAVOR_TNF_EXIT(tavor_special_qp_contexts_reserve);
2575		return (DDI_FAILURE);
2576	}
2577	state->ts_spec_qp0 = qp0_rsrc;
2578
2579	/*
2580	 * Reserve contexts for QP1.  These QP contexts will be setup to
2581	 * act as aliases for the real QP1.  Note: We are required to grab
2582	 * two QPs (one per port) even if we are operating in single-port
2583	 * mode.
2584	 */
2585	status = tavor_rsrc_alloc(state, TAVOR_QPC, 2, TAVOR_SLEEP, &qp1_rsrc);
2586	if (status != DDI_SUCCESS) {
2587		tavor_rsrc_free(state, &qp0_rsrc);
2588		mutex_destroy(&state->ts_spec_qplock);
2589		TNF_PROBE_0(tavor_special_qp_contexts_reserve_qp1_fail,
2590		    TAVOR_TNF_ERROR, "");
2591		TAVOR_TNF_EXIT(tavor_special_qp_contexts_reserve);
2592		return (DDI_FAILURE);
2593	}
2594	state->ts_spec_qp1 = qp1_rsrc;
2595
2596	TAVOR_TNF_EXIT(tavor_special_qp_contexts_reserve);
2597	return (DDI_SUCCESS);
2598}
2599
2600
2601/*
2602 * tavor_special_qp_contexts_unreserve()
2603 *    Context: Only called from attach() and/or detach() path contexts
2604 */
2605static void
2606tavor_special_qp_contexts_unreserve(tavor_state_t *state)
2607{
2608	TAVOR_TNF_ENTER(tavor_special_qp_contexts_unreserve);
2609
2610	/* Unreserve contexts for QP1 */
2611	tavor_rsrc_free(state, &state->ts_spec_qp1);
2612
2613	/* Unreserve contexts for QP0 */
2614	tavor_rsrc_free(state, &state->ts_spec_qp0);
2615
2616	/* Destroy the lock used for special QP rsrc management */
2617	mutex_destroy(&state->ts_spec_qplock);
2618
2619	TAVOR_TNF_EXIT(tavor_special_qp_contexts_unreserve);
2620}
2621
2622
2623/*
2624 * tavor_sw_reset()
2625 *    Context: Currently called only from attach() path context
2626 */
2627static int
2628tavor_sw_reset(tavor_state_t *state)
2629{
2630	dev_info_t		*dip, *pdip;
2631	ddi_acc_handle_t	hdl = state->ts_pci_cfghdl, phdl;
2632	uint32_t		reset_delay;
2633	int			status, i;
2634
2635	TAVOR_TNF_ENTER(tavor_sw_reset);
2636
2637	/*
2638	 * If the configured software reset delay is set to zero, then we
2639	 * will not attempt a software reset of the Tavor device.
2640	 */
2641	reset_delay = state->ts_cfg_profile->cp_sw_reset_delay;
2642	if (reset_delay == 0) {
2643		TAVOR_TNF_EXIT(tavor_sw_reset);
2644		return (DDI_SUCCESS);
2645	}
2646
2647	/*
2648	 * Get dip for HCA device _and_ parent device as well.  Parent access
2649	 * is necessary here because software reset of the Tavor hardware
2650	 * will reinitialize both the config registers of the PCI bridge
2651	 * (parent, if it exists) and the IB HCA (self)
2652	 */
2653	dip  = state->ts_dip;
2654	pdip = ddi_get_parent(dip);
2655
2656	/* Query the PCI capabilities of the HCA device */
2657	tavor_pci_capability_list(state, hdl);
2658
2659	/*
2660	 * Read all PCI config info (reg0...reg63).  Note: According to the
2661	 * Tavor software reset application note, we should not read or
2662	 * restore the values in reg22 and reg23.
2663	 */
2664	for (i = 0; i < TAVOR_SW_RESET_NUMREGS; i++) {
2665		if ((i != TAVOR_SW_RESET_REG22_RSVD) &&
2666		    (i != TAVOR_SW_RESET_REG23_RSVD)) {
2667			state->ts_cfg_data[i]  = pci_config_get32(hdl, i << 2);
2668		}
2669	}
2670
2671	if (TAVOR_PARENT_IS_BRIDGE(pdip)) {
2672		/*
2673		 * Setup for PCI config read/write of bridge device
2674		 */
2675		status = pci_config_setup(pdip, &phdl);
2676		if (status != DDI_SUCCESS) {
2677			TNF_PROBE_0(tavor_sw_reset_pcicfg_p_fail,
2678			    TAVOR_TNF_ERROR, "");
2679			TAVOR_TNF_EXIT(tavor_sw_reset);
2680			return (DDI_FAILURE);
2681		}
2682
2683		/*
2684		 * Read all PCI config info (reg0...reg63).  Note: According to
2685		 * the Tavor software reset application note, we should not
2686		 * read or restore the values in reg22 and reg23.
2687		 */
2688		for (i = 0; i < TAVOR_SW_RESET_NUMREGS; i++) {
2689			if ((i != TAVOR_SW_RESET_REG22_RSVD) &&
2690			    (i != TAVOR_SW_RESET_REG23_RSVD)) {
2691				state->ts_cfg_pdata[i] =
2692				    pci_config_get32(phdl, i << 2);
2693			}
2694		}
2695	}
2696
2697	/*
2698	 * Perform the software reset (by writing 1 at offset 0xF0010)
2699	 */
2700	ddi_put32(state->ts_reg_cmdhdl, state->ts_cmd_regs.sw_reset,
2701	    TAVOR_SW_RESET_START);
2702
2703	drv_usecwait(reset_delay);
2704
2705	if (TAVOR_PARENT_IS_BRIDGE(pdip)) {
2706		/*
2707		 * Bridge exists, so wait for the bridge to become ready.
2708		 *
2709		 * The above delay is necessary to avoid system panic from
2710		 * Master Abort.  If the device is accessed before this delay,
2711		 * device will not respond to config cycles and they will be
2712		 * terminate with a Master Abort which will panic the system.
2713		 * Below is the loop we use to poll status from the device to
2714		 * determine if it is OK to proceed.
2715		 */
2716		i = 0;
2717		while (pci_config_get32(phdl, 0) == TAVOR_SW_RESET_NOTDONE) {
2718			drv_usecwait(TAVOR_SW_RESET_POLL_DELAY);
2719		}
2720
2721		/*
2722		 * Write all the PCI config registers back into each device
2723		 * (except for reg22 and reg23 - see above)
2724		 */
2725		for (i = 0; i < TAVOR_SW_RESET_NUMREGS; i++) {
2726			if ((i != TAVOR_SW_RESET_REG22_RSVD) &&
2727			    (i != TAVOR_SW_RESET_REG23_RSVD)) {
2728				pci_config_put32(phdl, i << 2,
2729				    state->ts_cfg_pdata[i]);
2730			}
2731		}
2732
2733		/*
2734		 * Tear down the config setup (for bridge device)
2735		 */
2736		pci_config_teardown(&phdl);
2737
2738	/* No Bridge Device */
2739	} else {
2740		/*
2741		 * Bridge does not exist, so instead wait for the device itself
2742		 * to become ready.
2743		 *
2744		 * The above delay is necessary to avoid system panic from
2745		 * Master Abort.  If the device is accessed before this delay,
2746		 * device will not respond to config cycles and they will be
2747		 * terminate with a Master Abort which will panic the system.
2748		 * Below is the loop we use to poll status from the device to
2749		 * determine if it is OK to proceed.
2750		 */
2751		i = 0;
2752		while (pci_config_get32(hdl, 0) == TAVOR_SW_RESET_NOTDONE) {
2753			drv_usecwait(TAVOR_SW_RESET_POLL_DELAY);
2754		}
2755	}
2756
2757	for (i = 0; i < TAVOR_SW_RESET_NUMREGS; i++) {
2758		if ((i != TAVOR_SW_RESET_REG22_RSVD) &&
2759		    (i != TAVOR_SW_RESET_REG23_RSVD)) {
2760			pci_config_put32(hdl, i << 2, state->ts_cfg_data[i]);
2761		}
2762	}
2763
2764	TAVOR_TNF_EXIT(tavor_sw_reset);
2765	return (DDI_SUCCESS);
2766}
2767
2768
2769/*
2770 * tavor_mcg_init()
2771 *    Context: Only called from attach() path context
2772 */
2773static int
2774tavor_mcg_init(tavor_state_t *state)
2775{
2776	uint_t		mcg_tmp_sz;
2777
2778	TAVOR_TNF_ENTER(tavor_mcg_init);
2779
2780	/*
2781	 * Allocate space for the MCG temporary copy buffer.  This is
2782	 * used by the Attach/Detach Multicast Group code
2783	 */
2784	mcg_tmp_sz = TAVOR_MCGMEM_SZ(state);
2785	state->ts_mcgtmp = kmem_zalloc(mcg_tmp_sz, KM_SLEEP);
2786
2787	/*
2788	 * Initialize the multicast group mutex.  This ensures atomic
2789	 * access to add, modify, and remove entries in the multicast
2790	 * group hash lists.
2791	 */
2792	mutex_init(&state->ts_mcglock, NULL, MUTEX_DRIVER,
2793	    DDI_INTR_PRI(state->ts_intrmsi_pri));
2794
2795	TAVOR_TNF_EXIT(tavor_mcg_init);
2796	return (DDI_SUCCESS);
2797}
2798
2799
2800/*
2801 * tavor_mcg_fini()
2802 *    Context: Only called from attach() and/or detach() path contexts
2803 */
2804static void
2805tavor_mcg_fini(tavor_state_t *state)
2806{
2807	uint_t		mcg_tmp_sz;
2808
2809	TAVOR_TNF_ENTER(tavor_mcg_fini);
2810
2811	/* Free up the space used for the MCG temporary copy buffer */
2812	mcg_tmp_sz = TAVOR_MCGMEM_SZ(state);
2813	kmem_free(state->ts_mcgtmp, mcg_tmp_sz);
2814
2815	/* Destroy the multicast group mutex */
2816	mutex_destroy(&state->ts_mcglock);
2817
2818	TAVOR_TNF_EXIT(tavor_mcg_fini);
2819}
2820
2821
2822/*
2823 * tavor_fw_version_check()
2824 *    Context: Only called from attach() path context
2825 */
2826static int
2827tavor_fw_version_check(tavor_state_t *state)
2828{
2829	uint_t	tavor_fw_ver_major;
2830	uint_t	tavor_fw_ver_minor;
2831	uint_t	tavor_fw_ver_subminor;
2832
2833	/*
2834	 * Depending on which version of driver we have attached, the firmware
2835	 * version checks will be different.  We set up the comparison values
2836	 * for both HCA Mode (Tavor hardware) or COMPAT Mode (Arbel hardware
2837	 * running in tavor mode).
2838	 */
2839	switch (state->ts_operational_mode) {
2840	case TAVOR_HCA_MODE:
2841		tavor_fw_ver_major = TAVOR_FW_VER_MAJOR;
2842		tavor_fw_ver_minor = TAVOR_FW_VER_MINOR;
2843		tavor_fw_ver_subminor = TAVOR_FW_VER_SUBMINOR;
2844		break;
2845
2846	case TAVOR_COMPAT_MODE:
2847		tavor_fw_ver_major = TAVOR_COMPAT_FW_VER_MAJOR;
2848		tavor_fw_ver_minor = TAVOR_COMPAT_FW_VER_MINOR;
2849		tavor_fw_ver_subminor = TAVOR_COMPAT_FW_VER_SUBMINOR;
2850		break;
2851
2852	default:
2853		return (DDI_FAILURE);
2854	}
2855
2856	/*
2857	 * If FW revision major number is less than acceptable,
2858	 * return failure, else if greater return success.  If
2859	 * the major numbers are equal than check the minor number
2860	 */
2861	if (state->ts_fw.fw_rev_major < tavor_fw_ver_major) {
2862		return (DDI_FAILURE);
2863	} else if (state->ts_fw.fw_rev_major > tavor_fw_ver_major) {
2864		return (DDI_SUCCESS);
2865	}
2866	/*
2867	 * Do the same check as above, except for minor revision numbers
2868	 * If the minor numbers are equal than check the subminor number
2869	 */
2870	if (state->ts_fw.fw_rev_minor < tavor_fw_ver_minor) {
2871		return (DDI_FAILURE);
2872	} else if (state->ts_fw.fw_rev_minor > tavor_fw_ver_minor) {
2873		return (DDI_SUCCESS);
2874	}
2875
2876	/*
2877	 * Once again we do the same check as above, except for the subminor
2878	 * revision number.  If the subminor numbers are equal here, then
2879	 * these are the same firmware version, return success
2880	 */
2881	if (state->ts_fw.fw_rev_subminor < tavor_fw_ver_subminor) {
2882		return (DDI_FAILURE);
2883	} else if (state->ts_fw.fw_rev_subminor > tavor_fw_ver_subminor) {
2884		return (DDI_SUCCESS);
2885	}
2886
2887	return (DDI_SUCCESS);
2888}
2889
2890
2891/*
2892 * tavor_device_info_report()
2893 *    Context: Only called from attach() path context
2894 */
2895static void
2896tavor_device_info_report(tavor_state_t *state)
2897{
2898	cmn_err(CE_CONT, "?tavor%d: FW ver: %04d.%04d.%04d, "
2899	    "HW rev: %02x\n", state->ts_instance, state->ts_fw.fw_rev_major,
2900	    state->ts_fw.fw_rev_minor, state->ts_fw.fw_rev_subminor,
2901	    state->ts_adapter.rev_id);
2902	cmn_err(CE_CONT, "?tavor%d: %64s (0x%016" PRIx64 ")\n",
2903	    state->ts_instance, state->ts_nodedesc, state->ts_nodeguid);
2904}
2905
2906
2907/*
2908 * tavor_pci_capability_list()
2909 *    Context: Only called from attach() path context
2910 */
2911static void
2912tavor_pci_capability_list(tavor_state_t *state, ddi_acc_handle_t hdl)
2913{
2914	uint_t	offset, data;
2915
2916	TAVOR_TNF_ENTER(tavor_pci_capability_list);
2917
2918	/*
2919	 * Check for the "PCI Capabilities" bit in the "Status Register".
2920	 * Bit 4 in this register indicates the presence of a "PCI
2921	 * Capabilities" list.
2922	 */
2923	data = pci_config_get16(hdl, 0x6);
2924	if ((data & 0x10) == 0) {
2925		TNF_PROBE_0(tavor_pci_capab_list_fail, TAVOR_TNF_ERROR, "");
2926		TAVOR_TNF_EXIT(tavor_pci_capability_list);
2927		return;
2928	}
2929
2930	/*
2931	 * Starting from offset 0x34 in PCI config space, find the
2932	 * head of "PCI capabilities" list, and walk the list.  If
2933	 * capabilities of a known type are encountered (e.g.
2934	 * "PCI-X Capability"), then call the appropriate handler
2935	 * function.
2936	 */
2937	offset = pci_config_get8(hdl, 0x34);
2938	while (offset != 0x0) {
2939		data = pci_config_get8(hdl, offset);
2940
2941		/*
2942		 * Check for known capability types.  Tavor has the
2943		 * following:
2944		 *    o VPD Capability   (0x03)
2945		 *    o PCI-X Capability (0x07)
2946		 *    o MSI Capability   (0x05)
2947		 *    o MSIX Capability  (0x11)
2948		 */
2949		switch (data) {
2950		case 0x03:
2951			tavor_pci_capability_vpd(state, hdl, offset);
2952			break;
2953		case 0x07:
2954			tavor_pci_capability_pcix(state, hdl, offset);
2955			break;
2956		case 0x05:
2957			break;
2958		default:
2959			break;
2960		}
2961
2962		/* Get offset of next entry in list */
2963		offset = pci_config_get8(hdl, offset + 1);
2964	}
2965
2966	TAVOR_TNF_EXIT(tavor_pci_capability_list);
2967}
2968
2969/*
2970 * tavor_pci_read_vpd()
2971 *    Context: Only called from attach() path context
2972 *    utility routine for tavor_pci_capability_vpd()
2973 */
2974static int
2975tavor_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset, uint32_t addr,
2976    uint32_t *data)
2977{
2978	int		retry = 4;  /* retry counter for EEPROM poll */
2979	uint32_t	val;
2980	int		vpd_addr = offset + 2;
2981	int		vpd_data = offset + 4;
2982
2983	TAVOR_TNF_ENTER(tavor_pci_read_vpd);
2984
2985	/*
2986	 * In order to read a 32-bit value from VPD, we are to write down
2987	 * the address (offset in the VPD itself) to the address register.
2988	 * To signal the read, we also clear bit 31.  We then poll on bit 31
2989	 * and when it is set, we can then read our 4 bytes from the data
2990	 * register.
2991	 */
2992	(void) pci_config_put32(hdl, offset, addr << 16);
2993	do {
2994		drv_usecwait(1000);
2995		val = pci_config_get16(hdl, vpd_addr);
2996		if ((val >> 15) & 0x01) {
2997			*data = pci_config_get32(hdl, vpd_data);
2998			TAVOR_TNF_EXIT(tavor_pci_read_vpd);
2999			return (DDI_SUCCESS);
3000		}
3001	} while (--retry);
3002
3003	TNF_PROBE_0(tavor_pci_read_vpd_fail, TAVOR_TNF_ERROR, "");
3004	TAVOR_TNF_EXIT(tavor_pci_read_vpd);
3005	return (DDI_FAILURE);
3006}
3007
3008
3009/*
3010 * tavor_pci_capability_vpd()
3011 *    Context: Only called from attach() path context
3012 */
3013static void
3014tavor_pci_capability_vpd(tavor_state_t *state, ddi_acc_handle_t hdl,
3015    uint_t offset)
3016{
3017	uint8_t			name_length;
3018	uint8_t			pn_length;
3019	int			i, err = 0;
3020	int			vpd_str_id = 0;
3021	int			vpd_ro_desc;
3022	int			vpd_ro_pn_desc;
3023#ifndef _LITTLE_ENDIAN
3024	uint32_t		data32;
3025#endif /* _LITTLE_ENDIAN */
3026	union {
3027		uint32_t	vpd_int[TAVOR_VPD_HDR_DWSIZE];
3028		uchar_t		vpd_char[TAVOR_VPD_HDR_BSIZE];
3029	} vpd;
3030
3031	TAVOR_TNF_ENTER(tavor_pci_capability_vpd);
3032
3033	/*
3034	 * Read Vital Product Data (VPD) from PCI-X capability.
3035	 */
3036	for (i = 0; i < TAVOR_VPD_HDR_DWSIZE; i++) {
3037		err = tavor_pci_read_vpd(hdl, offset, i << 2, &vpd.vpd_int[i]);
3038		if (err != DDI_SUCCESS) {
3039			cmn_err(CE_NOTE, "!VPD read failed\n");
3040			goto out;
3041		}
3042	}
3043
3044#ifndef _LITTLE_ENDIAN
3045	/*
3046	 * Need to swap bytes for big endian.
3047	 */
3048	for (i = 0; i < TAVOR_VPD_HDR_DWSIZE; i++) {
3049		data32 = vpd.vpd_int[i];
3050		vpd.vpd_char[(i << 2) + 3] =
3051		    (uchar_t)((data32 & 0xFF000000) >> 24);
3052		vpd.vpd_char[(i << 2) + 2] =
3053		    (uchar_t)((data32 & 0x00FF0000) >> 16);
3054		vpd.vpd_char[(i << 2) + 1] =
3055		    (uchar_t)((data32 & 0x0000FF00) >> 8);
3056		vpd.vpd_char[i << 2] = (uchar_t)(data32 & 0x000000FF);
3057	}
3058#endif	/* _LITTLE_ENDIAN */
3059
3060	/* Check for VPD String ID Tag */
3061	if (vpd.vpd_char[vpd_str_id] == 0x82) {
3062		/* get the product name */
3063		name_length = (uint8_t)vpd.vpd_char[vpd_str_id + 1];
3064		if (name_length > sizeof (state->ts_hca_name)) {
3065			cmn_err(CE_NOTE, "!VPD name too large (0x%x)\n",
3066			    name_length);
3067			goto out;
3068		}
3069		(void) memcpy(state->ts_hca_name, &vpd.vpd_char[vpd_str_id + 3],
3070		    name_length);
3071		state->ts_hca_name[name_length] = 0;
3072
3073		/* get the part number */
3074		vpd_ro_desc = name_length + 3; /* read-only tag location */
3075		vpd_ro_pn_desc = vpd_ro_desc + 3; /* P/N keyword location */
3076		/*
3077		 * Verify read-only tag and Part Number keyword.
3078		 */
3079		if (vpd.vpd_char[vpd_ro_desc] != 0x90 ||
3080		    (vpd.vpd_char[vpd_ro_pn_desc] != 'P' &&
3081		    vpd.vpd_char[vpd_ro_pn_desc + 1] != 'N')) {
3082			cmn_err(CE_NOTE, "!VPD Part Number not found\n");
3083			goto out;
3084		}
3085
3086		pn_length = (uint8_t)vpd.vpd_char[vpd_ro_pn_desc + 2];
3087		if (pn_length > sizeof (state->ts_hca_pn)) {
3088			cmn_err(CE_NOTE, "!VPD part number too large (0x%x)\n",
3089			    name_length);
3090			goto out;
3091		}
3092		(void) memcpy(state->ts_hca_pn,
3093		    &vpd.vpd_char[vpd_ro_pn_desc + 3],
3094		    pn_length);
3095		state->ts_hca_pn[pn_length] = 0;
3096		state->ts_hca_pn_len = pn_length;
3097	} else {
3098		/* Wrong VPD String ID Tag */
3099		cmn_err(CE_NOTE, "!VPD String ID Tag not found, tag: %02x\n",
3100		    vpd.vpd_char[0]);
3101		goto out;
3102	}
3103	TAVOR_TNF_EXIT(tavor_pci_capability_vpd);
3104	return;
3105out:
3106	state->ts_hca_pn_len = 0;
3107	TNF_PROBE_0(tavor_pci_capability_vpd_fail, TAVOR_TNF_ERROR, "");
3108	TAVOR_TNF_EXIT(tavor_pci_capability_vpd);
3109}
3110
3111/*
3112 * tavor_pci_capability_pcix()
3113 *    Context: Only called from attach() path context
3114 */
3115static void
3116tavor_pci_capability_pcix(tavor_state_t *state, ddi_acc_handle_t hdl,
3117    uint_t offset)
3118{
3119	uint_t	command, status;
3120	int	max_out_splt_trans, max_mem_rd_byte_cnt;
3121	int	designed_max_out_splt_trans, designed_max_mem_rd_byte_cnt;
3122
3123	TAVOR_TNF_ENTER(tavor_pci_capability_pcix);
3124
3125	/*
3126	 * Query the current values for the PCI-X Command Register and
3127	 * the PCI-X Status Register.
3128	 */
3129	command = pci_config_get16(hdl, offset + 2);
3130	status  = pci_config_get32(hdl, offset + 4);
3131
3132	/*
3133	 * Check for config property specifying "maximum outstanding
3134	 * split transactions".  If the property is defined and valid
3135	 * (i.e. no larger than the so-called "designed maximum"),
3136	 * then use the specified value to update the PCI-X Command Register.
3137	 * Otherwise, extract the value from the Tavor config profile.
3138	 */
3139	designed_max_out_splt_trans = ((status >> 23) & 7);
3140	max_out_splt_trans = ddi_prop_get_int(DDI_DEV_T_ANY, state->ts_dip,
3141	    DDI_PROP_DONTPASS, "pcix-max-outstanding-split-trans", -1);
3142	if ((max_out_splt_trans != -1) &&
3143	    ((max_out_splt_trans < 0) ||
3144	    (max_out_splt_trans > designed_max_out_splt_trans))) {
3145		cmn_err(CE_NOTE, "!tavor%d: property \"pcix-max-outstanding-"
3146		    "split-trans\" (%d) invalid or exceeds device maximum"
3147		    " (%d), using default value (%d)\n", state->ts_instance,
3148		    max_out_splt_trans, designed_max_out_splt_trans,
3149		    state->ts_cfg_profile->cp_max_out_splt_trans);
3150		max_out_splt_trans =
3151		    state->ts_cfg_profile->cp_max_out_splt_trans;
3152	} else if (max_out_splt_trans == -1) {
3153		max_out_splt_trans =
3154		    state->ts_cfg_profile->cp_max_out_splt_trans;
3155	}
3156
3157	/*
3158	 * The config profile setting for max_out_splt_trans is determined
3159	 * based on arch.  Check tavor_cfg.c for more information.  A value of
3160	 * '-1' in the patchable variable means "do not change".  A value of
3161	 * '0' means 1 outstanding splt trans and other values as defined by
3162	 * PCI.  So we do one more check here, that if 'max_out_splt_trans' is
3163	 * -1 (ie: < 0) we do not set the PCI command and leave it at the
3164	 * default.
3165	 */
3166	if (max_out_splt_trans >= 0) {
3167		command = ((command & 0xFF8F) | max_out_splt_trans << 4);
3168	}
3169
3170	/*
3171	 * Check for config property specifying "maximum memory read
3172	 * byte count.  If the property is defined and valid
3173	 * (i.e. no larger than the so-called "designed maximum"),
3174	 * then use the specified value to update the PCI-X Command Register.
3175	 * Otherwise, extract the value from the Tavor config profile.
3176	 */
3177	designed_max_mem_rd_byte_cnt = ((status >> 21) & 3);
3178	max_mem_rd_byte_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, state->ts_dip,
3179	    DDI_PROP_DONTPASS, "pcix-max-read-byte-count", -1);
3180	if ((max_mem_rd_byte_cnt != -1) &&
3181	    ((max_mem_rd_byte_cnt < 0) ||
3182	    (max_mem_rd_byte_cnt > designed_max_mem_rd_byte_cnt))) {
3183		cmn_err(CE_NOTE, "!tavor%d: property \"pcix-max-read-byte-"
3184		    "count\" (%d) invalid or exceeds device maximum"
3185		    " (%d), using default value (%d)\n", state->ts_instance,
3186		    max_mem_rd_byte_cnt, designed_max_mem_rd_byte_cnt,
3187		    state->ts_cfg_profile->cp_max_mem_rd_byte_cnt);
3188		max_mem_rd_byte_cnt =
3189		    state->ts_cfg_profile->cp_max_mem_rd_byte_cnt;
3190	} else if (max_mem_rd_byte_cnt == -1) {
3191		max_mem_rd_byte_cnt =
3192		    state->ts_cfg_profile->cp_max_mem_rd_byte_cnt;
3193	}
3194
3195	/*
3196	 * The config profile setting for max_mem_rd_byte_cnt is determined
3197	 * based on arch.  Check tavor_cfg.c for more information.  A value of
3198	 * '-1' in the patchable variable means "do not change".  A value of
3199	 * '0' means minimum (512B) read, and other values as defined by
3200	 * PCI.  So we do one more check here, that if 'max_mem_rd_byte_cnt' is
3201	 * -1 (ie: < 0) we do not set the PCI command and leave it at the
3202	 * default.
3203	 */
3204	if (max_mem_rd_byte_cnt >= 0) {
3205		command = ((command & 0xFFF3) | max_mem_rd_byte_cnt << 2);
3206	}
3207
3208	/*
3209	 * Update the PCI-X Command Register with the newly configured
3210	 * values.
3211	 */
3212	pci_config_put16(hdl, offset + 2, command);
3213
3214	TAVOR_TNF_EXIT(tavor_pci_capability_pcix);
3215}
3216
3217
3218/*
3219 * tavor_intr_or_msi_init()
3220 *    Context: Only called from attach() path context
3221 */
3222static int
3223tavor_intr_or_msi_init(tavor_state_t *state)
3224{
3225	int	status;
3226
3227	TAVOR_TNF_ENTER(tavor_intr_or_msi_init);
3228
3229	/* Query for the list of supported interrupt event types */
3230	status = ddi_intr_get_supported_types(state->ts_dip,
3231	    &state->ts_intr_types_avail);
3232	if (status != DDI_SUCCESS) {
3233		TNF_PROBE_0(tavor_intr_or_msi_init_gettypes_fail,
3234		    TAVOR_TNF_ERROR, "");
3235		TAVOR_TNF_EXIT(tavor_intr_or_msi_init);
3236		return (DDI_FAILURE);
3237	}
3238
3239	/*
3240	 * If Tavor/Arbel supports MSI in this system (and, if it
3241	 * hasn't been overridden by a configuration variable), then
3242	 * the default behavior is to use a single MSI.  Otherwise,
3243	 * fallback to using legacy interrupts.  Also, if MSI allocatis chosen,
3244	 * but fails for whatever reasons, then fallback to using legacy
3245	 * interrupts.
3246	 */
3247	if ((state->ts_cfg_profile->cp_use_msi_if_avail != 0) &&
3248	    (state->ts_intr_types_avail & DDI_INTR_TYPE_MSI)) {
3249		status = tavor_add_intrs(state, DDI_INTR_TYPE_MSI);
3250		if (status == DDI_SUCCESS) {
3251			state->ts_intr_type_chosen = DDI_INTR_TYPE_MSI;
3252			TAVOR_TNF_EXIT(tavor_intr_or_msi_init);
3253			return (DDI_SUCCESS);
3254		}
3255	}
3256
3257	/*
3258	 * MSI interrupt allocation failed, or was not available.  Fallback to
3259	 * legacy interrupt support.
3260	 */
3261	if (state->ts_intr_types_avail & DDI_INTR_TYPE_FIXED) {
3262		status = tavor_add_intrs(state, DDI_INTR_TYPE_FIXED);
3263		if (status == DDI_SUCCESS) {
3264			state->ts_intr_type_chosen = DDI_INTR_TYPE_FIXED;
3265			TAVOR_TNF_EXIT(tavor_intr_or_msi_init);
3266			return (DDI_SUCCESS);
3267		}
3268	}
3269
3270	/*
3271	 * Neither MSI or legacy interrupts were successful.  return failure.
3272	 */
3273	TAVOR_TNF_EXIT(tavor_intr_or_msi_setup);
3274	return (DDI_FAILURE);
3275}
3276
3277/*
3278 * tavor_add_intrs()
3279 *    Context: Only called from attach() patch context
3280 */
3281static int
3282tavor_add_intrs(tavor_state_t *state, int intr_type)
3283{
3284	int status;
3285
3286	TAVOR_TNF_ENTER(tavor_add_intrs);
3287
3288	/* Get number of interrupts/MSI supported */
3289	status = ddi_intr_get_nintrs(state->ts_dip, intr_type,
3290	    &state->ts_intrmsi_count);
3291	if (status != DDI_SUCCESS) {
3292		TNF_PROBE_0(tavor_add_intrs_getnintrs_fail,
3293		    TAVOR_TNF_ERROR, "");
3294		TAVOR_TNF_EXIT(tavor_add_intrs);
3295		return (DDI_FAILURE);
3296	}
3297
3298	/* Get number of available interrupts/MSI */
3299	status = ddi_intr_get_navail(state->ts_dip, intr_type,
3300	    &state->ts_intrmsi_avail);
3301	if (status != DDI_SUCCESS) {
3302		TNF_PROBE_0(tavor_add_intrs_getnavail_fail,
3303		    TAVOR_TNF_ERROR, "");
3304		TAVOR_TNF_EXIT(tavor_add_intrs);
3305		return (DDI_FAILURE);
3306	}
3307
3308	/* Ensure that we have at least one (1) usable MSI or interrupt */
3309	if ((state->ts_intrmsi_avail < 1) || (state->ts_intrmsi_count < 1)) {
3310		TNF_PROBE_0(tavor_add_intrs_notenoughts_intrmsi_fail,
3311		    TAVOR_TNF_ERROR, "");
3312		TAVOR_TNF_EXIT(tavor_add_intrs);
3313		return (DDI_FAILURE);
3314	}
3315
3316	/* Attempt to allocate a single interrupt/MSI handle */
3317	status = ddi_intr_alloc(state->ts_dip, &state->ts_intrmsi_hdl,
3318	    intr_type, 0, 1, &state->ts_intrmsi_allocd,
3319	    DDI_INTR_ALLOC_STRICT);
3320	if (status != DDI_SUCCESS) {
3321		TNF_PROBE_0(tavor_add_intrs_intralloc_fail,
3322		    TAVOR_TNF_ERROR, "");
3323		TAVOR_TNF_EXIT(tavor_add_intrs);
3324		return (DDI_FAILURE);
3325	}
3326
3327	/* Ensure that we have allocated at least one (1) MSI or interrupt */
3328	if (state->ts_intrmsi_allocd < 1) {
3329		TNF_PROBE_0(tavor_add_intrs_noallocts_intrmsi_fail,
3330		    TAVOR_TNF_ERROR, "");
3331		TAVOR_TNF_EXIT(tavor_add_intrs);
3332		return (DDI_FAILURE);
3333	}
3334
3335	/*
3336	 * Extract the priority for the allocated interrupt/MSI.  This
3337	 * will be used later when initializing certain mutexes.
3338	 */
3339	status = ddi_intr_get_pri(state->ts_intrmsi_hdl,
3340	    &state->ts_intrmsi_pri);
3341	if (status != DDI_SUCCESS) {
3342		/* Free the allocated interrupt/MSI handle */
3343		(void) ddi_intr_free(state->ts_intrmsi_hdl);
3344
3345		TNF_PROBE_0(tavor_add_intrs_getpri_fail,
3346		    TAVOR_TNF_ERROR, "");
3347		TAVOR_TNF_EXIT(tavor_add_intrs);
3348		return (DDI_FAILURE);
3349	}
3350
3351	/* Make sure the interrupt/MSI priority is below 'high level' */
3352	if (state->ts_intrmsi_pri >= ddi_intr_get_hilevel_pri()) {
3353		/* Free the allocated interrupt/MSI handle */
3354		(void) ddi_intr_free(state->ts_intrmsi_hdl);
3355
3356		TNF_PROBE_0(tavor_add_intrs_hilevelpri_fail,
3357		    TAVOR_TNF_ERROR, "");
3358		TAVOR_TNF_EXIT(tavor_add_intrs);
3359		return (DDI_FAILURE);
3360	}
3361
3362	/* Get add'l capability information regarding interrupt/MSI */
3363	status = ddi_intr_get_cap(state->ts_intrmsi_hdl,
3364	    &state->ts_intrmsi_cap);
3365	if (status != DDI_SUCCESS) {
3366		/* Free the allocated interrupt/MSI handle */
3367		(void) ddi_intr_free(state->ts_intrmsi_hdl);
3368
3369		TNF_PROBE_0(tavor_add_intrs_getcap_fail,
3370		    TAVOR_TNF_ERROR, "");
3371		TAVOR_TNF_EXIT(tavor_add_intrs);
3372		return (DDI_FAILURE);
3373	}
3374
3375	TAVOR_TNF_EXIT(tavor_add_intrs);
3376	return (DDI_SUCCESS);
3377}
3378
3379
3380/*
3381 * tavor_intr_or_msi_fini()
3382 *    Context: Only called from attach() and/or detach() path contexts
3383 */
3384static int
3385tavor_intr_or_msi_fini(tavor_state_t *state)
3386{
3387	int	status;
3388
3389	TAVOR_TNF_ENTER(tavor_intr_or_msi_fini);
3390
3391	/* Free the allocated interrupt/MSI handle */
3392	status = ddi_intr_free(state->ts_intrmsi_hdl);
3393	if (status != DDI_SUCCESS) {
3394		TNF_PROBE_0(tavor_intr_or_msi_fini_freehdl_fail,
3395		    TAVOR_TNF_ERROR, "");
3396		TAVOR_TNF_EXIT(tavor_intr_or_msi_fini);
3397		return (DDI_FAILURE);
3398	}
3399
3400	TAVOR_TNF_EXIT(tavor_intr_or_msi_fini);
3401	return (DDI_SUCCESS);
3402}
3403
3404
3405/* Disable Tavor interrupts */
3406static int
3407tavor_intr_disable(tavor_state_t *state)
3408{
3409	ushort_t msi_ctrl = 0, caps_ctrl = 0;
3410	ddi_acc_handle_t pci_cfg_hdl = state->ts_pci_cfghdl;
3411	ASSERT(pci_cfg_hdl != NULL);
3412	ASSERT(state->ts_intr_types_avail &
3413	    (DDI_INTR_TYPE_FIXED | DDI_INTR_TYPE_MSI));
3414
3415	/*
3416	 * Check if MSI interrupts are used. If so, disable MSI interupts.
3417	 * If not, since Tavor doesn't support MSI-X interrupts, assuming the
3418	 * legacy interrupt is used instead, disable the legacy interrupt.
3419	 */
3420	if ((state->ts_cfg_profile->cp_use_msi_if_avail != 0) &&
3421	    (state->ts_intr_types_avail & DDI_INTR_TYPE_MSI)) {
3422
3423		if ((PCI_CAP_LOCATE(pci_cfg_hdl, PCI_CAP_ID_MSI,
3424		    &caps_ctrl) == DDI_SUCCESS)) {
3425			if ((msi_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL,
3426			    caps_ctrl, PCI_MSI_CTRL)) == PCI_CAP_EINVAL16)
3427				return (DDI_FAILURE);
3428		}
3429		ASSERT(msi_ctrl != 0);
3430
3431		if (!(msi_ctrl & PCI_MSI_ENABLE_BIT))
3432			return (DDI_SUCCESS);
3433
3434		if (msi_ctrl &  PCI_MSI_PVM_MASK) {
3435			int offset = (msi_ctrl &  PCI_MSI_64BIT_MASK) ?
3436			    PCI_MSI_64BIT_MASKBITS : PCI_MSI_32BIT_MASK;
3437
3438			/* Clear all inums in MSI */
3439			PCI_CAP_PUT32(pci_cfg_hdl, NULL, caps_ctrl,
3440			    offset, 0x0);
3441		}
3442
3443		/* Disable MSI interrupts */
3444		msi_ctrl &= ~PCI_MSI_ENABLE_BIT;
3445		PCI_CAP_PUT16(pci_cfg_hdl, NULL, caps_ctrl, PCI_MSI_CTRL,
3446		    msi_ctrl);
3447
3448	} else {
3449		uint16_t cmdreg = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
3450		ASSERT(state->ts_intr_types_avail & DDI_INTR_TYPE_FIXED);
3451
3452		/* Disable the legacy interrupts */
3453		cmdreg |= PCI_COMM_INTX_DISABLE;
3454		pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, cmdreg);
3455	}
3456
3457	return (DDI_SUCCESS);
3458}
3459
3460/* Tavor quiesce(9F) entry */
3461static int
3462tavor_quiesce(dev_info_t *dip)
3463{
3464	tavor_state_t *state = ddi_get_soft_state(tavor_statep,
3465	    DEVI(dip)->devi_instance);
3466	ASSERT(state != NULL);
3467
3468	/* start fastreboot */
3469	state->ts_quiescing = B_TRUE;
3470
3471	/* Shutdown HCA ports */
3472	if (tavor_hca_ports_shutdown(state,
3473	    state->ts_cfg_profile->cp_num_ports) != TAVOR_CMD_SUCCESS) {
3474		state->ts_quiescing = B_FALSE;
3475		return (DDI_FAILURE);
3476	}
3477
3478	/* Close HCA */
3479	if (tavor_close_hca_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN) !=
3480	    TAVOR_CMD_SUCCESS) {
3481		state->ts_quiescing = B_FALSE;
3482		return (DDI_FAILURE);
3483	}
3484
3485	/* Shutdown FW */
3486	if (tavor_sys_dis_cmd_post(state, TAVOR_CMD_NOSLEEP_SPIN) !=
3487	    TAVOR_CMD_SUCCESS) {
3488		state->ts_quiescing = B_FALSE;
3489		return (DDI_FAILURE);
3490	}
3491
3492	/* Disable interrupts */
3493	if (tavor_intr_disable(state) != DDI_SUCCESS) {
3494		state->ts_quiescing = B_FALSE;
3495		return (DDI_FAILURE);
3496	}
3497
3498	/* SW-reset */
3499	if (tavor_sw_reset(state) != DDI_SUCCESS) {
3500		state->ts_quiescing = B_FALSE;
3501		return (DDI_FAILURE);
3502	}
3503
3504	return (DDI_SUCCESS);
3505}
3506