xref: /onnv-gate/usr/src/uts/sun4/io/px/px_msiq.c (revision 10923:df470fd79c3c)
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 /*
2210053SEvan.Yan@Sun.COM  * Copyright 2009 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 
43*10923SEvan.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
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 	 */
63*10923SEvan.Yan@Sun.COM 	if (px_msiq_get_props(px_p) != DDI_SUCCESS)
64*10923SEvan.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 	mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL);
810Sstevel@tonic-gate 	msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt *
820Sstevel@tonic-gate 	    sizeof (px_msiq_t), KM_SLEEP);
830Sstevel@tonic-gate 
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 
930Sstevel@tonic-gate 	if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS)
940Sstevel@tonic-gate 		px_msiq_detach(px_p);
950Sstevel@tonic-gate 
9610053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_redist_flag = B_TRUE;
970Sstevel@tonic-gate 	return (ret);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate  * px_msiq_detach()
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate void
1040Sstevel@tonic-gate px_msiq_detach(px_t *px_p)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n");
1090Sstevel@tonic-gate 
1107124Sanbui 	if (px_lib_msiq_fini(px_p->px_dip) != DDI_SUCCESS) {
1117124Sanbui 		DBG(DBG_MSIQ, px_p->px_dip,
1127124Sanbui 		    "px_lib_msiq_fini: failed\n");
1137124Sanbui 	}
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	mutex_destroy(&msiq_state_p->msiq_mutex);
1160Sstevel@tonic-gate 	kmem_free(msiq_state_p->msiq_p,
1170Sstevel@tonic-gate 	    msiq_state_p->msiq_cnt * sizeof (px_msiq_t));
1180Sstevel@tonic-gate 
11910053SEvan.Yan@Sun.COM 	bzero(msiq_state_p, sizeof (px_msiq_state_t));
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate /*
12310053SEvan.Yan@Sun.COM  * px_msiq_resume()
1242588Segillett  */
1252588Segillett void
1262588Segillett px_msiq_resume(px_t *px_p)
1272588Segillett {
1282973Sgovinda 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1292588Segillett 	int		i;
1302588Segillett 
1312973Sgovinda 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
13210053SEvan.Yan@Sun.COM 		(void) px_lib_msiq_gethead(px_p->px_dip,
13310053SEvan.Yan@Sun.COM 		    msiq_state_p->msiq_p[i].msiq_id,
1342973Sgovinda 		    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
1352973Sgovinda 		msiq_state_p->msiq_p[i].msiq_new_head_index = 0;
1362973Sgovinda 		msiq_state_p->msiq_p[i].msiq_recs2process = 0;
1372973Sgovinda 	}
1382588Segillett }
1392588Segillett 
1402588Segillett /*
1410Sstevel@tonic-gate  * px_msiq_alloc()
1420Sstevel@tonic-gate  */
1430Sstevel@tonic-gate int
14410841SAlan.Adamson@Sun.COM px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msgcode_t msg_code,
14510841SAlan.Adamson@Sun.COM     msiqid_t *msiq_id_p)
1460Sstevel@tonic-gate {
14710053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
14810053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
14910053SEvan.Yan@Sun.COM 	msiqid_t	first_msiq_id;
1500Sstevel@tonic-gate 	uint_t		msiq_cnt;
15110053SEvan.Yan@Sun.COM 	ushort_t	least_refcnt;
1520Sstevel@tonic-gate 	int		i;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n");
1550Sstevel@tonic-gate 
15610053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
15710053SEvan.Yan@Sun.COM 	mutex_enter(&msiq_state_p->msiq_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 			mutex_exit(&msiq_state_p->msiq_mutex);
18410841SAlan.Adamson@Sun.COM 			return (DDI_SUCCESS);
18510841SAlan.Adamson@Sun.COM 		}
18610841SAlan.Adamson@Sun.COM 
18710841SAlan.Adamson@Sun.COM 		/* Jump past the first/dedicated EQ */
18810841SAlan.Adamson@Sun.COM 		first_msiq_id++;
18910841SAlan.Adamson@Sun.COM 		msiq_cnt = msiq_state_p->msiq_msg_qcnt - 1;
19010053SEvan.Yan@Sun.COM 	} else {
19110053SEvan.Yan@Sun.COM 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
19210053SEvan.Yan@Sun.COM 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
19310053SEvan.Yan@Sun.COM 	}
19410053SEvan.Yan@Sun.COM 
19510053SEvan.Yan@Sun.COM 	*msiq_id_p = first_msiq_id;
19610053SEvan.Yan@Sun.COM 	least_refcnt = msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt;
19710053SEvan.Yan@Sun.COM 
19810053SEvan.Yan@Sun.COM 	/* Allocate MSIQs */
19910053SEvan.Yan@Sun.COM 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
20010053SEvan.Yan@Sun.COM 		if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) {
20110053SEvan.Yan@Sun.COM 			msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE;
20210053SEvan.Yan@Sun.COM 			(void) px_lib_msiq_gethead(px_p->px_dip, i,
20310053SEvan.Yan@Sun.COM 			    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
20410053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
20510053SEvan.Yan@Sun.COM 			break;
20610053SEvan.Yan@Sun.COM 		}
20710053SEvan.Yan@Sun.COM 
20810053SEvan.Yan@Sun.COM 		if (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt) {
20910053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
21010053SEvan.Yan@Sun.COM 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
21110053SEvan.Yan@Sun.COM 		}
21210053SEvan.Yan@Sun.COM 	}
21310053SEvan.Yan@Sun.COM 
21410053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
21510053SEvan.Yan@Sun.COM 
21610053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip,
21710053SEvan.Yan@Sun.COM 	    "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
21810053SEvan.Yan@Sun.COM 
21910053SEvan.Yan@Sun.COM 	mutex_exit(&msiq_state_p->msiq_mutex);
22010053SEvan.Yan@Sun.COM 	return (DDI_SUCCESS);
22110053SEvan.Yan@Sun.COM }
22210053SEvan.Yan@Sun.COM 
22310053SEvan.Yan@Sun.COM /*
22410053SEvan.Yan@Sun.COM  * px_msiq_alloc_based_on_cpuid()
22510053SEvan.Yan@Sun.COM  */
22610053SEvan.Yan@Sun.COM int
22710053SEvan.Yan@Sun.COM px_msiq_alloc_based_on_cpuid(px_t *px_p, msiq_rec_type_t rec_type,
22810053SEvan.Yan@Sun.COM     cpuid_t cpuid, msiqid_t *msiq_id_p)
22910053SEvan.Yan@Sun.COM {
23010053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
23110053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
23210053SEvan.Yan@Sun.COM 	msiqid_t	first_msiq_id, free_msiq_id;
23310053SEvan.Yan@Sun.COM 	uint_t		msiq_cnt;
23410053SEvan.Yan@Sun.COM 	ushort_t	least_refcnt;
23510053SEvan.Yan@Sun.COM 	px_ino_t	*ino_p;
23610053SEvan.Yan@Sun.COM 	int		i;
23710053SEvan.Yan@Sun.COM 
23810053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc_based_on_cpuid: "
23910053SEvan.Yan@Sun.COM 	    "cpuid 0x%x\n", cpuid);
24010053SEvan.Yan@Sun.COM 
24110053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
24210053SEvan.Yan@Sun.COM 
2430Sstevel@tonic-gate 	mutex_enter(&msiq_state_p->msiq_mutex);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	if (rec_type == MSG_REC) {
2460Sstevel@tonic-gate 		msiq_cnt = msiq_state_p->msiq_msg_qcnt;
2470Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
2480Sstevel@tonic-gate 	} else {
2490Sstevel@tonic-gate 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
2500Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
25310053SEvan.Yan@Sun.COM 	*msiq_id_p = free_msiq_id = (msiqid_t)-1;
25410053SEvan.Yan@Sun.COM 	least_refcnt = (ushort_t)-1;
25510053SEvan.Yan@Sun.COM 
2560Sstevel@tonic-gate 	/* Allocate MSIQs */
2570Sstevel@tonic-gate 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
25810053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p, px_msiqid_to_devino(px_p, i));
25910053SEvan.Yan@Sun.COM 
26010053SEvan.Yan@Sun.COM 		if ((ino_p->ino_cpuid == cpuid) &&
26110053SEvan.Yan@Sun.COM 		    (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt)) {
26210053SEvan.Yan@Sun.COM 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
26310053SEvan.Yan@Sun.COM 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
2640Sstevel@tonic-gate 		}
26510053SEvan.Yan@Sun.COM 
26610053SEvan.Yan@Sun.COM 		if ((*msiq_id_p == -1) && (free_msiq_id == -1) &&
26710053SEvan.Yan@Sun.COM 		    (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE))
26810053SEvan.Yan@Sun.COM 			free_msiq_id = msiq_state_p->msiq_p[i].msiq_id;
2690Sstevel@tonic-gate 	}
2700Sstevel@tonic-gate 
27110053SEvan.Yan@Sun.COM 	if (*msiq_id_p == -1) {
27210053SEvan.Yan@Sun.COM 		if (free_msiq_id == -1) {
27310053SEvan.Yan@Sun.COM 			DBG(DBG_MSIQ, px_p->px_dip,
27410053SEvan.Yan@Sun.COM 			    "px_msiq_alloc_based_on_cpuid: No EQ is available "
27510053SEvan.Yan@Sun.COM 			    "for CPU 0x%x\n", cpuid);
27610053SEvan.Yan@Sun.COM 
27710053SEvan.Yan@Sun.COM 			mutex_exit(&msiq_state_p->msiq_mutex);
27810053SEvan.Yan@Sun.COM 			return (DDI_EINVAL);
27910053SEvan.Yan@Sun.COM 		}
28010053SEvan.Yan@Sun.COM 
28110053SEvan.Yan@Sun.COM 		*msiq_id_p = free_msiq_id;
28210053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p,
28310053SEvan.Yan@Sun.COM 		    px_msiqid_to_devino(px_p, *msiq_id_p));
28410053SEvan.Yan@Sun.COM 		ino_p->ino_cpuid = ino_p->ino_default_cpuid = cpuid;
2852973Sgovinda 	}
2860Sstevel@tonic-gate 
28710053SEvan.Yan@Sun.COM 	if (msiq_state_p->msiq_p[*msiq_id_p].msiq_state == MSIQ_STATE_FREE) {
28810053SEvan.Yan@Sun.COM 		msiq_state_p->msiq_p[*msiq_id_p].msiq_state = MSIQ_STATE_INUSE;
28910053SEvan.Yan@Sun.COM 		(void) px_lib_msiq_gethead(px_p->px_dip, *msiq_id_p,
29010053SEvan.Yan@Sun.COM 		    &msiq_state_p->msiq_p[*msiq_id_p].msiq_curr_head_index);
29110053SEvan.Yan@Sun.COM 	}
2920Sstevel@tonic-gate 
29310053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
2940Sstevel@tonic-gate 
29510053SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip,
29610053SEvan.Yan@Sun.COM 	    "px_msiq_alloc_based_on_cpuid: msiq_id 0x%x\n", *msiq_id_p);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	mutex_exit(&msiq_state_p->msiq_mutex);
2990Sstevel@tonic-gate 	return (DDI_SUCCESS);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate  * px_msiq_free()
3040Sstevel@tonic-gate  */
3050Sstevel@tonic-gate int
3060Sstevel@tonic-gate px_msiq_free(px_t *px_p, msiqid_t msiq_id)
3070Sstevel@tonic-gate {
30810053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
30910053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id);
3120Sstevel@tonic-gate 
31310053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
3140Sstevel@tonic-gate 	mutex_enter(&msiq_state_p->msiq_mutex);
3150Sstevel@tonic-gate 
3162973Sgovinda 	if ((msiq_id < msiq_state_p->msiq_1st_msiq_id) || (msiq_id >=
3172973Sgovinda 	    (msiq_state_p->msiq_1st_msiq_id + msiq_state_p->msiq_cnt))) {
3182973Sgovinda 		DBG(DBG_MSIQ, px_p->px_dip,
3192973Sgovinda 		    "px_msiq_free: Invalid msiq_id 0x%x", msiq_id);
32010053SEvan.Yan@Sun.COM 
32110053SEvan.Yan@Sun.COM 		mutex_exit(&msiq_state_p->msiq_mutex);
3222973Sgovinda 		return (DDI_FAILURE);
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 
3252973Sgovinda 	if (--msiq_state_p->msiq_p[msiq_id].msiq_refcnt == 0)
3262973Sgovinda 		msiq_state_p->msiq_p[msiq_id].msiq_state = MSIQ_STATE_FREE;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	mutex_exit(&msiq_state_p->msiq_mutex);
3292973Sgovinda 	return (DDI_SUCCESS);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate /*
33310053SEvan.Yan@Sun.COM  * px_msiq_redist()
33410053SEvan.Yan@Sun.COM  */
33510053SEvan.Yan@Sun.COM void
33610053SEvan.Yan@Sun.COM px_msiq_redist(px_t *px_p)
33710053SEvan.Yan@Sun.COM {
33810053SEvan.Yan@Sun.COM 	px_ib_t		*ib_p = px_p->px_ib_p;
33910053SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
34010053SEvan.Yan@Sun.COM 	px_ino_t	*ino_p;
34110053SEvan.Yan@Sun.COM 	int		i;
34210053SEvan.Yan@Sun.COM 
34310053SEvan.Yan@Sun.COM 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
34410053SEvan.Yan@Sun.COM 
34510053SEvan.Yan@Sun.COM 	mutex_enter(&msiq_state_p->msiq_mutex);
34610053SEvan.Yan@Sun.COM 
34710053SEvan.Yan@Sun.COM 	if (msiq_state_p->msiq_redist_flag == B_FALSE) {
34810053SEvan.Yan@Sun.COM 		mutex_exit(&msiq_state_p->msiq_mutex);
34910053SEvan.Yan@Sun.COM 		return;
35010053SEvan.Yan@Sun.COM 	}
35110053SEvan.Yan@Sun.COM 
35210053SEvan.Yan@Sun.COM 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
35310053SEvan.Yan@Sun.COM 		ino_p = px_ib_locate_ino(ib_p,
35410053SEvan.Yan@Sun.COM 		    px_msiqid_to_devino(px_p, msiq_state_p->msiq_p[i].msiq_id));
35510053SEvan.Yan@Sun.COM 
35610053SEvan.Yan@Sun.COM 		if (ino_p) {
35710053SEvan.Yan@Sun.COM 			ino_p->ino_cpuid = ino_p->ino_default_cpuid =
35810053SEvan.Yan@Sun.COM 			    intr_dist_cpuid();
35910053SEvan.Yan@Sun.COM 
36010053SEvan.Yan@Sun.COM 			DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_redist: "
36110053SEvan.Yan@Sun.COM 			    "sysino 0x%llx current cpuid 0x%x "
36210053SEvan.Yan@Sun.COM 			    "default cpuid 0x%x\n", ino_p->ino_sysino,
36310053SEvan.Yan@Sun.COM 			    ino_p->ino_cpuid, ino_p->ino_default_cpuid);
36410053SEvan.Yan@Sun.COM 		}
36510053SEvan.Yan@Sun.COM 	}
36610053SEvan.Yan@Sun.COM 
36710053SEvan.Yan@Sun.COM 	msiq_state_p->msiq_redist_flag = B_FALSE;
36810053SEvan.Yan@Sun.COM 	mutex_exit(&msiq_state_p->msiq_mutex);
36910053SEvan.Yan@Sun.COM }
37010053SEvan.Yan@Sun.COM 
37110053SEvan.Yan@Sun.COM /*
3720Sstevel@tonic-gate  * px_msiqid_to_devino()
3730Sstevel@tonic-gate  */
3740Sstevel@tonic-gate devino_t
3750Sstevel@tonic-gate px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3780Sstevel@tonic-gate 	devino_t	devino;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	devino = msiq_state_p->msiq_1st_devino +
3810Sstevel@tonic-gate 	    msiq_id - msiq_state_p->msiq_1st_msiq_id;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: "
3840Sstevel@tonic-gate 	    "msiq_id 0x%x devino 0x%x\n", msiq_id, devino);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	return (devino);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate  * px_devino_to_msiqid()
3910Sstevel@tonic-gate  */
3920Sstevel@tonic-gate msiqid_t
3930Sstevel@tonic-gate px_devino_to_msiqid(px_t *px_p, devino_t devino)
3940Sstevel@tonic-gate {
3950Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3960Sstevel@tonic-gate 	msiqid_t	msiq_id;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	msiq_id = msiq_state_p->msiq_1st_msiq_id +
3990Sstevel@tonic-gate 	    devino - msiq_state_p->msiq_1st_devino;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: "
4020Sstevel@tonic-gate 	    "devino 0x%x msiq_id 0x%x\n", devino, msiq_id);
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	return (msiq_id);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate  * px_msiq_get_props()
4090Sstevel@tonic-gate  */
410*10923SEvan.Yan@Sun.COM static int
4110Sstevel@tonic-gate px_msiq_get_props(px_t *px_p)
4120Sstevel@tonic-gate {
413*10923SEvan.Yan@Sun.COM 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
414*10923SEvan.Yan@Sun.COM 	int		length = sizeof (int);
415*10923SEvan.Yan@Sun.COM 	char		*valuep = NULL;
416*10923SEvan.Yan@Sun.COM 	int		ret;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n");
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	/* #msi-eqs */
4210Sstevel@tonic-gate 	msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
422*10923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "#msi-eqs", 0);
4230Sstevel@tonic-gate 
424*10923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_cnt=%d\n", msiq_state_p->msiq_cnt);
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	/* msi-eq-size */
4270Sstevel@tonic-gate 	msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
428*10923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "msi-eq-size", 0);
4290Sstevel@tonic-gate 
430*10923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_rec_cnt=%d\n",
4310Sstevel@tonic-gate 	    msiq_state_p->msiq_rec_cnt);
4320Sstevel@tonic-gate 
433*10923SEvan.Yan@Sun.COM 	if ((msiq_state_p->msiq_cnt == 0) || (msiq_state_p->msiq_rec_cnt == 0))
434*10923SEvan.Yan@Sun.COM 		return (DDI_FAILURE);
435*10923SEvan.Yan@Sun.COM 
4360Sstevel@tonic-gate 	/* msi-eq-to-devino: msi-eq#, devino# fields */
4370Sstevel@tonic-gate 	ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC,
438*10923SEvan.Yan@Sun.COM 	    DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, &length);
4390Sstevel@tonic-gate 
440*10923SEvan.Yan@Sun.COM 	/*
441*10923SEvan.Yan@Sun.COM 	 * NOTE:
442*10923SEvan.Yan@Sun.COM 	 * On sun4u PCIe systems, the msi-eq-to-devino property is broken and
443*10923SEvan.Yan@Sun.COM 	 * these systems defines this property as msi-eq-devino.
444*10923SEvan.Yan@Sun.COM 	 */
445*10923SEvan.Yan@Sun.COM 	if (ret == DDI_PROP_NOT_FOUND) {
446*10923SEvan.Yan@Sun.COM 		DBG(DBG_MSIQ, px_p->px_dip, "msi-eq-to-devino is not found\n");
447*10923SEvan.Yan@Sun.COM 		ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip,
448*10923SEvan.Yan@Sun.COM 		    PROP_LEN_AND_VAL_ALLOC, DDI_PROP_DONTPASS, "msi-eq-devino",
449*10923SEvan.Yan@Sun.COM 		    (caddr_t)&valuep, &length);
4500Sstevel@tonic-gate 	}
4510Sstevel@tonic-gate 
452*10923SEvan.Yan@Sun.COM 	if (ret != DDI_PROP_SUCCESS) {
453*10923SEvan.Yan@Sun.COM 		return (DDI_FAILURE);
454*10923SEvan.Yan@Sun.COM 	}
455*10923SEvan.Yan@Sun.COM 
456*10923SEvan.Yan@Sun.COM 	msiq_state_p->msiq_1st_msiq_id =
457*10923SEvan.Yan@Sun.COM 	    ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no;
458*10923SEvan.Yan@Sun.COM 	msiq_state_p->msiq_1st_devino =
459*10923SEvan.Yan@Sun.COM 	    ((px_msi_eq_to_devino_t *)valuep)->devino_no;
460*10923SEvan.Yan@Sun.COM 
461*10923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_msiq_id=%d\n",
4620Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_msiq_id);
4630Sstevel@tonic-gate 
464*10923SEvan.Yan@Sun.COM 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_devino=%d\n",
4650Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_devino);
466*10923SEvan.Yan@Sun.COM 
467*10923SEvan.Yan@Sun.COM 	kmem_free(valuep, (size_t)length);
468*10923SEvan.Yan@Sun.COM 	return (DDI_SUCCESS);
4690Sstevel@tonic-gate }
470