xref: /onnv-gate/usr/src/uts/sun4/io/px/px_msiq.c (revision 11520:d8fe7b2bbee2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52588Segillett  * Common Development and Distribution License (the "License").
62588Segillett  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11520SScott.Carter@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * px_msiq.c
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/kmem.h>
320Sstevel@tonic-gate #include <sys/conf.h>
330Sstevel@tonic-gate #include <sys/ddi.h>
340Sstevel@tonic-gate #include <sys/sunddi.h>
3510841SAlan.Adamson@Sun.COM #include <sys/sysmacros.h>
3610053SEvan.Yan@Sun.COM #include <sys/machsystm.h>	/* intr_dist_add */
370Sstevel@tonic-gate #include <sys/modctl.h>
380Sstevel@tonic-gate #include <sys/disp.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
410Sstevel@tonic-gate #include "px_obj.h"
420Sstevel@tonic-gate 
4310923SEvan.Yan@Sun.COM static int px_msiq_get_props(px_t *px_p);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * px_msiq_attach()
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate int
px_msiq_attach(px_t * px_p)490Sstevel@tonic-gate px_msiq_attach(px_t *px_p)
500Sstevel@tonic-gate {
5110053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
5210053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
5310841SAlan.Adamson@Sun.COM 	int		qcnt, i, ret = DDI_SUCCESS;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n");
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 	/*
580Sstevel@tonic-gate 	 * Check for all MSIQ related properties and
590Sstevel@tonic-gate 	 * save all information.
600Sstevel@tonic-gate 	 *
610Sstevel@tonic-gate 	 * Avaialble MSIQs and its properties.
620Sstevel@tonic-gate 	 */
6310923SEvan.Yan@Sun.COM 	if (px_msiq_get_props(px_p) != DDI_SUCCESS)
6410923SEvan.Yan@Sun.COM 		return (DDI_FAILURE);
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	/*
670Sstevel@tonic-gate 	 * 10% of available MSIQs are reserved for the PCIe messages.
680Sstevel@tonic-gate 	 * Around 90% of available MSIQs are reserved for the MSI/Xs.
690Sstevel@tonic-gate 	 */
700Sstevel@tonic-gate 	msiq_state_p->msiq_msg_qcnt = howmany(msiq_state_p->msiq_cnt, 10);
7110841SAlan.Adamson@Sun.COM 
7210841SAlan.Adamson@Sun.COM 	qcnt = MIN(msiq_state_p->msiq_msg_qcnt, px_max_msiq_msgs);
7310841SAlan.Adamson@Sun.COM 	msiq_state_p->msiq_msg_qcnt = qcnt = MAX(qcnt, px_min_msiq_msgs);
7410841SAlan.Adamson@Sun.COM 	msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - qcnt;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id;
770Sstevel@tonic-gate 	msiq_state_p->msiq_1st_msg_qid = msiq_state_p->msiq_1st_msiq_id +
780Sstevel@tonic-gate 	    msiq_state_p->msiq_msi_qcnt;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt *
810Sstevel@tonic-gate 	    sizeof (px_msiq_t), KM_SLEEP);
820Sstevel@tonic-gate 
83*11520SScott.Carter@Sun.COM 	mutex_enter(&ib_p->ib_ino_lst_mutex);
840Sstevel@tonic-gate 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
850Sstevel@tonic-gate 		msiq_state_p->msiq_p[i].msiq_id =
860Sstevel@tonic-gate 		    msiq_state_p->msiq_1st_msiq_id + i;
872973Sgovinda 		msiq_state_p->msiq_p[i].msiq_refcnt = 0;
880Sstevel@tonic-gate 		msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE;
8910053SEvan.Yan@Sun.COM 		(void) px_ib_alloc_ino(ib_p, px_msiqid_to_devino(px_p,
9010053SEvan.Yan@Sun.COM 		    msiq_state_p->msiq_p[i].msiq_id));
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate 
93*11520SScott.Carter@Sun.COM 	msiq_state_p->msiq_redist_flag = B_TRUE;
94*11520SScott.Carter@Sun.COM 	mutex_exit(&ib_p->ib_ino_lst_mutex);
95*11520SScott.Carter@Sun.COM 
960Sstevel@tonic-gate 	if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS)
970Sstevel@tonic-gate 		px_msiq_detach(px_p);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	return (ret);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate  * px_msiq_detach()
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate void
px_msiq_detach(px_t * px_p)1060Sstevel@tonic-gate px_msiq_detach(px_t *px_p)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n");
1110Sstevel@tonic-gate 
1127124Sanbui 	if (px_lib_msiq_fini(px_p->px_dip) != DDI_SUCCESS) {
1137124Sanbui 		DBG(DBG_MSIQ, px_p->px_dip,
1147124Sanbui 		    "px_lib_msiq_fini: failed\n");
1157124Sanbui 	}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	kmem_free(msiq_state_p->msiq_p,
1180Sstevel@tonic-gate 	    msiq_state_p->msiq_cnt * sizeof (px_msiq_t));
1190Sstevel@tonic-gate 
12010053SEvan.Yan@Sun.COM 	bzero(msiq_state_p, sizeof (px_msiq_state_t));
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate /*
12410053SEvan.Yan@Sun.COM  * px_msiq_resume()
1252588Segillett  */
1262588Segillett void
px_msiq_resume(px_t * px_p)1272588Segillett px_msiq_resume(px_t *px_p)
1282588Segillett {
1292973Sgovinda 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1302588Segillett 	int		i;
1312588Segillett 
1322973Sgovinda 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
13310053SEvan.Yan@Sun.COM 		(void) px_lib_msiq_gethead(px_p->px_dip,
13410053SEvan.Yan@Sun.COM 		    msiq_state_p->msiq_p[i].msiq_id,
1352973Sgovinda 		    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
1362973Sgovinda 		msiq_state_p->msiq_p[i].msiq_new_head_index = 0;
1372973Sgovinda 		msiq_state_p->msiq_p[i].msiq_recs2process = 0;
1382973Sgovinda 	}
1392588Segillett }
1402588Segillett 
1412588Segillett /*
1420Sstevel@tonic-gate  * px_msiq_alloc()
1430Sstevel@tonic-gate  */
1440Sstevel@tonic-gate int
px_msiq_alloc(px_t * px_p,msiq_rec_type_t rec_type,msgcode_t msg_code,msiqid_t * msiq_id_p)14510841SAlan.Adamson@Sun.COM px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msgcode_t msg_code,
14610841SAlan.Adamson@Sun.COM     msiqid_t *msiq_id_p)
1470Sstevel@tonic-gate {
14810053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
14910053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
15010053SEvan.Yan@Sun.COM 	msiqid_t	first_msiq_id;
1510Sstevel@tonic-gate 	uint_t		msiq_cnt;
15210053SEvan.Yan@Sun.COM 	ushort_t	least_refcnt;
1530Sstevel@tonic-gate 	int		i;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n");
1560Sstevel@tonic-gate 
15710053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
15810053SEvan.Yan@Sun.COM 
15910053SEvan.Yan@Sun.COM 	if (rec_type == MSG_REC) {
16010841SAlan.Adamson@Sun.COM 		/*
16110841SAlan.Adamson@Sun.COM 		 * The first MSG EQ is dedicated to PCIE_MSG_CODE_ERR_COR
16210841SAlan.Adamson@Sun.COM 		 * messages. All other messages will be spread across
16310841SAlan.Adamson@Sun.COM 		 * the remaining MSG EQs.
16410841SAlan.Adamson@Sun.COM 		 */
16510053SEvan.Yan@Sun.COM 		first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
16610841SAlan.Adamson@Sun.COM 
16710841SAlan.Adamson@Sun.COM 		if (msg_code == PCIE_MSG_CODE_ERR_COR) {
16810841SAlan.Adamson@Sun.COM 			msiq_state_p->msiq_p[first_msiq_id].msiq_state =
16910841SAlan.Adamson@Sun.COM 			    MSIQ_STATE_INUSE;
17010841SAlan.Adamson@Sun.COM 
17110841SAlan.Adamson@Sun.COM 			(void) px_lib_msiq_gethead(px_p->px_dip, first_msiq_id,
17210841SAlan.Adamson@Sun.COM 			    &msiq_state_p->msiq_p[first_msiq_id].
17310841SAlan.Adamson@Sun.COM 			    msiq_curr_head_index);
17410841SAlan.Adamson@Sun.COM 
17510841SAlan.Adamson@Sun.COM 			*msiq_id_p =
17610841SAlan.Adamson@Sun.COM 			    msiq_state_p->msiq_p[first_msiq_id].msiq_id;
17710841SAlan.Adamson@Sun.COM 
17810841SAlan.Adamson@Sun.COM 			msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt++;
17910841SAlan.Adamson@Sun.COM 
18010841SAlan.Adamson@Sun.COM 			DBG(DBG_MSIQ, px_p->px_dip,
18110841SAlan.Adamson@Sun.COM 			    "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
18210841SAlan.Adamson@Sun.COM 
18310841SAlan.Adamson@Sun.COM 			return (DDI_SUCCESS);
18410841SAlan.Adamson@Sun.COM 		}
18510841SAlan.Adamson@Sun.COM 
18610841SAlan.Adamson@Sun.COM 		/* Jump past the first/dedicated EQ */
18710841SAlan.Adamson@Sun.COM 		first_msiq_id++;
18810841SAlan.Adamson@Sun.COM 		msiq_cnt = msiq_state_p->msiq_msg_qcnt - 1;
18910053SEvan.Yan@Sun.COM 	} else {
19010053SEvan.Yan@Sun.COM 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
19110053SEvan.Yan@Sun.COM 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
19210053SEvan.Yan@Sun.COM 	}
19310053SEvan.Yan@Sun.COM 
19410053SEvan.Yan@Sun.COM 	*msiq_id_p = first_msiq_id;
19510053SEvan.Yan@Sun.COM 	least_refcnt = msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt;
19610053SEvan.Yan@Sun.COM 
19710053SEvan.Yan@Sun.COM 	/* Allocate MSIQs */
19810053SEvan.Yan@Sun.COM 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
19910053SEvan.Yan@Sun.COM 		if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) {
20010053SEvan.Yan@Sun.COM 			msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE;
20110053SEvan.Yan@Sun.COM 			(void) px_lib_msiq_gethead(px_p->px_dip, i,
20210053SEvan.Yan@Sun.COM 			    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
20310053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
20410053SEvan.Yan@Sun.COM 			break;
20510053SEvan.Yan@Sun.COM 		}
20610053SEvan.Yan@Sun.COM 
20710053SEvan.Yan@Sun.COM 		if (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt) {
20810053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
20910053SEvan.Yan@Sun.COM 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
21010053SEvan.Yan@Sun.COM 		}
21110053SEvan.Yan@Sun.COM 	}
21210053SEvan.Yan@Sun.COM 
21310053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
21410053SEvan.Yan@Sun.COM 
21510053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip,
21610053SEvan.Yan@Sun.COM 	    "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
21710053SEvan.Yan@Sun.COM 
21810053SEvan.Yan@Sun.COM 	return (DDI_SUCCESS);
21910053SEvan.Yan@Sun.COM }
22010053SEvan.Yan@Sun.COM 
22110053SEvan.Yan@Sun.COM /*
22210053SEvan.Yan@Sun.COM  * px_msiq_alloc_based_on_cpuid()
22310053SEvan.Yan@Sun.COM  */
22410053SEvan.Yan@Sun.COM int
px_msiq_alloc_based_on_cpuid(px_t * px_p,msiq_rec_type_t rec_type,cpuid_t cpuid,msiqid_t * msiq_id_p)22510053SEvan.Yan@Sun.COM px_msiq_alloc_based_on_cpuid(px_t *px_p, msiq_rec_type_t rec_type,
22610053SEvan.Yan@Sun.COM     cpuid_t cpuid, msiqid_t *msiq_id_p)
22710053SEvan.Yan@Sun.COM {
22810053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
22910053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
23010053SEvan.Yan@Sun.COM 	msiqid_t	first_msiq_id, free_msiq_id;
23110053SEvan.Yan@Sun.COM 	uint_t		msiq_cnt;
23210053SEvan.Yan@Sun.COM 	ushort_t	least_refcnt;
23310053SEvan.Yan@Sun.COM 	px_ino_t	*ino_p;
23410053SEvan.Yan@Sun.COM 	int		i;
23510053SEvan.Yan@Sun.COM 
23610053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc_based_on_cpuid: "
23710053SEvan.Yan@Sun.COM 	    "cpuid 0x%x\n", cpuid);
23810053SEvan.Yan@Sun.COM 
23910053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
24010053SEvan.Yan@Sun.COM 
2410Sstevel@tonic-gate 	if (rec_type == MSG_REC) {
2420Sstevel@tonic-gate 		msiq_cnt = msiq_state_p->msiq_msg_qcnt;
2430Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
2440Sstevel@tonic-gate 	} else {
2450Sstevel@tonic-gate 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
2460Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
24910053SEvan.Yan@Sun.COM 	*msiq_id_p = free_msiq_id = (msiqid_t)-1;
25010053SEvan.Yan@Sun.COM 	least_refcnt = (ushort_t)-1;
25110053SEvan.Yan@Sun.COM 
2520Sstevel@tonic-gate 	/* Allocate MSIQs */
2530Sstevel@tonic-gate 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
25410053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p, px_msiqid_to_devino(px_p, i));
25510053SEvan.Yan@Sun.COM 
25610053SEvan.Yan@Sun.COM 		if ((ino_p->ino_cpuid == cpuid) &&
25710053SEvan.Yan@Sun.COM 		    (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt)) {
25810053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
25910053SEvan.Yan@Sun.COM 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
2600Sstevel@tonic-gate 		}
26110053SEvan.Yan@Sun.COM 
26210053SEvan.Yan@Sun.COM 		if ((*msiq_id_p == -1) && (free_msiq_id == -1) &&
26310053SEvan.Yan@Sun.COM 		    (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE))
26410053SEvan.Yan@Sun.COM 			free_msiq_id = msiq_state_p->msiq_p[i].msiq_id;
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 
26710053SEvan.Yan@Sun.COM 	if (*msiq_id_p == -1) {
26810053SEvan.Yan@Sun.COM 		if (free_msiq_id == -1) {
26910053SEvan.Yan@Sun.COM 			DBG(DBG_MSIQ, px_p->px_dip,
27010053SEvan.Yan@Sun.COM 			    "px_msiq_alloc_based_on_cpuid: No EQ is available "
27110053SEvan.Yan@Sun.COM 			    "for CPU 0x%x\n", cpuid);
27210053SEvan.Yan@Sun.COM 			return (DDI_EINVAL);
27310053SEvan.Yan@Sun.COM 		}
27410053SEvan.Yan@Sun.COM 
27510053SEvan.Yan@Sun.COM 		*msiq_id_p = free_msiq_id;
27610053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p,
27710053SEvan.Yan@Sun.COM 		    px_msiqid_to_devino(px_p, *msiq_id_p));
27810053SEvan.Yan@Sun.COM 		ino_p->ino_cpuid = ino_p->ino_default_cpuid = cpuid;
2792973Sgovinda 	}
2800Sstevel@tonic-gate 
28110053SEvan.Yan@Sun.COM 	if (msiq_state_p->msiq_p[*msiq_id_p].msiq_state == MSIQ_STATE_FREE) {
28210053SEvan.Yan@Sun.COM 		msiq_state_p->msiq_p[*msiq_id_p].msiq_state = MSIQ_STATE_INUSE;
28310053SEvan.Yan@Sun.COM 		(void) px_lib_msiq_gethead(px_p->px_dip, *msiq_id_p,
28410053SEvan.Yan@Sun.COM 		    &msiq_state_p->msiq_p[*msiq_id_p].msiq_curr_head_index);
28510053SEvan.Yan@Sun.COM 	}
2860Sstevel@tonic-gate 
28710053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
2880Sstevel@tonic-gate 
28910053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip,
29010053SEvan.Yan@Sun.COM 	    "px_msiq_alloc_based_on_cpuid: msiq_id 0x%x\n", *msiq_id_p);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	return (DDI_SUCCESS);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate  * px_msiq_free()
2970Sstevel@tonic-gate  */
2980Sstevel@tonic-gate int
px_msiq_free(px_t * px_p,msiqid_t msiq_id)2990Sstevel@tonic-gate px_msiq_free(px_t *px_p, msiqid_t msiq_id)
3000Sstevel@tonic-gate {
30110053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
30210053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id);
3050Sstevel@tonic-gate 
30610053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
3070Sstevel@tonic-gate 
3082973Sgovinda 	if ((msiq_id < msiq_state_p->msiq_1st_msiq_id) || (msiq_id >=
3092973Sgovinda 	    (msiq_state_p->msiq_1st_msiq_id + msiq_state_p->msiq_cnt))) {
3102973Sgovinda 		DBG(DBG_MSIQ, px_p->px_dip,
3112973Sgovinda 		    "px_msiq_free: Invalid msiq_id 0x%x", msiq_id);
3122973Sgovinda 		return (DDI_FAILURE);
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3152973Sgovinda 	if (--msiq_state_p->msiq_p[msiq_id].msiq_refcnt == 0)
3162973Sgovinda 		msiq_state_p->msiq_p[msiq_id].msiq_state = MSIQ_STATE_FREE;
3170Sstevel@tonic-gate 
3182973Sgovinda 	return (DDI_SUCCESS);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate /*
32210053SEvan.Yan@Sun.COM  * px_msiq_redist()
32310053SEvan.Yan@Sun.COM  */
32410053SEvan.Yan@Sun.COM void
px_msiq_redist(px_t * px_p)32510053SEvan.Yan@Sun.COM px_msiq_redist(px_t *px_p)
32610053SEvan.Yan@Sun.COM {
32710053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
32810053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
32910053SEvan.Yan@Sun.COM 	px_ino_t	*ino_p;
33010053SEvan.Yan@Sun.COM 	int		i;
33110053SEvan.Yan@Sun.COM 
33210053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
33310053SEvan.Yan@Sun.COM 
334*11520SScott.Carter@Sun.COM 	if (msiq_state_p->msiq_redist_flag == B_FALSE)
33510053SEvan.Yan@Sun.COM 		return;
33610053SEvan.Yan@Sun.COM 
33710053SEvan.Yan@Sun.COM 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
33810053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p,
33910053SEvan.Yan@Sun.COM 		    px_msiqid_to_devino(px_p, msiq_state_p->msiq_p[i].msiq_id));
34010053SEvan.Yan@Sun.COM 
34110053SEvan.Yan@Sun.COM 		if (ino_p) {
34210053SEvan.Yan@Sun.COM 			ino_p->ino_cpuid = ino_p->ino_default_cpuid =
34310053SEvan.Yan@Sun.COM 			    intr_dist_cpuid();
34410053SEvan.Yan@Sun.COM 
34510053SEvan.Yan@Sun.COM 			DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_redist: "
34610053SEvan.Yan@Sun.COM 			    "sysino 0x%llx current cpuid 0x%x "
34710053SEvan.Yan@Sun.COM 			    "default cpuid 0x%x\n", ino_p->ino_sysino,
34810053SEvan.Yan@Sun.COM 			    ino_p->ino_cpuid, ino_p->ino_default_cpuid);
34910053SEvan.Yan@Sun.COM 		}
35010053SEvan.Yan@Sun.COM 	}
35110053SEvan.Yan@Sun.COM 
35210053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_redist_flag = B_FALSE;
35310053SEvan.Yan@Sun.COM }
35410053SEvan.Yan@Sun.COM 
35510053SEvan.Yan@Sun.COM /*
3560Sstevel@tonic-gate  * px_msiqid_to_devino()
3570Sstevel@tonic-gate  */
3580Sstevel@tonic-gate devino_t
px_msiqid_to_devino(px_t * px_p,msiqid_t msiq_id)3590Sstevel@tonic-gate px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3620Sstevel@tonic-gate 	devino_t	devino;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	devino = msiq_state_p->msiq_1st_devino +
3650Sstevel@tonic-gate 	    msiq_id - msiq_state_p->msiq_1st_msiq_id;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: "
3680Sstevel@tonic-gate 	    "msiq_id 0x%x devino 0x%x\n", msiq_id, devino);
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	return (devino);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate /*
3740Sstevel@tonic-gate  * px_devino_to_msiqid()
3750Sstevel@tonic-gate  */
3760Sstevel@tonic-gate msiqid_t
px_devino_to_msiqid(px_t * px_p,devino_t devino)3770Sstevel@tonic-gate px_devino_to_msiqid(px_t *px_p, devino_t devino)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3800Sstevel@tonic-gate 	msiqid_t	msiq_id;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	msiq_id = msiq_state_p->msiq_1st_msiq_id +
3830Sstevel@tonic-gate 	    devino - msiq_state_p->msiq_1st_devino;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: "
3860Sstevel@tonic-gate 	    "devino 0x%x msiq_id 0x%x\n", devino, msiq_id);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	return (msiq_id);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate /*
3920Sstevel@tonic-gate  * px_msiq_get_props()
3930Sstevel@tonic-gate  */
39410923SEvan.Yan@Sun.COM static int
px_msiq_get_props(px_t * px_p)3950Sstevel@tonic-gate px_msiq_get_props(px_t *px_p)
3960Sstevel@tonic-gate {
39710923SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
39810923SEvan.Yan@Sun.COM 	int		length = sizeof (int);
39910923SEvan.Yan@Sun.COM 	char		*valuep = NULL;
40010923SEvan.Yan@Sun.COM 	int		ret;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n");
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	/* #msi-eqs */
4050Sstevel@tonic-gate 	msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
40610923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "#msi-eqs", 0);
4070Sstevel@tonic-gate 
40810923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_cnt=%d\n", msiq_state_p->msiq_cnt);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	/* msi-eq-size */
4110Sstevel@tonic-gate 	msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
41210923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "msi-eq-size", 0);
4130Sstevel@tonic-gate 
41410923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_rec_cnt=%d\n",
4150Sstevel@tonic-gate 	    msiq_state_p->msiq_rec_cnt);
4160Sstevel@tonic-gate 
41710923SEvan.Yan@Sun.COM 	if ((msiq_state_p->msiq_cnt == 0) || (msiq_state_p->msiq_rec_cnt == 0))
41810923SEvan.Yan@Sun.COM 		return (DDI_FAILURE);
41910923SEvan.Yan@Sun.COM 
4200Sstevel@tonic-gate 	/* msi-eq-to-devino: msi-eq#, devino# fields */
4210Sstevel@tonic-gate 	ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC,
42210923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, &length);
4230Sstevel@tonic-gate 
42410923SEvan.Yan@Sun.COM 	/*
42510923SEvan.Yan@Sun.COM 	 * NOTE:
42610923SEvan.Yan@Sun.COM 	 * On sun4u PCIe systems, the msi-eq-to-devino property is broken and
42710923SEvan.Yan@Sun.COM 	 * these systems defines this property as msi-eq-devino.
42810923SEvan.Yan@Sun.COM 	 */
42910923SEvan.Yan@Sun.COM 	if (ret == DDI_PROP_NOT_FOUND) {
43010923SEvan.Yan@Sun.COM 		DBG(DBG_MSIQ, px_p->px_dip, "msi-eq-to-devino is not found\n");
43110923SEvan.Yan@Sun.COM 		ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip,
43210923SEvan.Yan@Sun.COM 		    PROP_LEN_AND_VAL_ALLOC, DDI_PROP_DONTPASS, "msi-eq-devino",
43310923SEvan.Yan@Sun.COM 		    (caddr_t)&valuep, &length);
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 
43610923SEvan.Yan@Sun.COM 	if (ret != DDI_PROP_SUCCESS) {
43710923SEvan.Yan@Sun.COM 		return (DDI_FAILURE);
43810923SEvan.Yan@Sun.COM 	}
43910923SEvan.Yan@Sun.COM 
44010923SEvan.Yan@Sun.COM 	msiq_state_p->msiq_1st_msiq_id =
44110923SEvan.Yan@Sun.COM 	    ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no;
44210923SEvan.Yan@Sun.COM 	msiq_state_p->msiq_1st_devino =
44310923SEvan.Yan@Sun.COM 	    ((px_msi_eq_to_devino_t *)valuep)->devino_no;
44410923SEvan.Yan@Sun.COM 
44510923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_msiq_id=%d\n",
4460Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_msiq_id);
4470Sstevel@tonic-gate 
44810923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_devino=%d\n",
4490Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_devino);
45010923SEvan.Yan@Sun.COM 
45110923SEvan.Yan@Sun.COM 	kmem_free(valuep, (size_t)length);
45210923SEvan.Yan@Sun.COM 	return (DDI_SUCCESS);
4530Sstevel@tonic-gate }
454