xref: /illumos-gate/usr/src/uts/sun4/io/px/px_msiq.c (revision d17daf0b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5023ccc1eSegillett  * Common Development and Distribution License (the "License").
6023ccc1eSegillett  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*d17daf0bSScott Carter, SD IOSW  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * px_msiq.c
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
327c478bd9Sstevel@tonic-gate #include <sys/conf.h>
337c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
3518191143SAlan Adamson, SD OSSD #include <sys/sysmacros.h>
3609b1eac2SEvan Yan #include <sys/machsystm.h>	/* intr_dist_add */
377c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
387c478bd9Sstevel@tonic-gate #include <sys/disp.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
417c478bd9Sstevel@tonic-gate #include "px_obj.h"
427c478bd9Sstevel@tonic-gate 
4326947304SEvan Yan static int px_msiq_get_props(px_t *px_p);
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * px_msiq_attach()
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate int
px_msiq_attach(px_t * px_p)497c478bd9Sstevel@tonic-gate px_msiq_attach(px_t *px_p)
507c478bd9Sstevel@tonic-gate {
5109b1eac2SEvan Yan 	px_ib_t		*ib_p = px_p->px_ib_p;
5209b1eac2SEvan Yan 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
5318191143SAlan Adamson, SD OSSD 	int		qcnt, i, ret = DDI_SUCCESS;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n");
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	/*
587c478bd9Sstevel@tonic-gate 	 * Check for all MSIQ related properties and
597c478bd9Sstevel@tonic-gate 	 * save all information.
607c478bd9Sstevel@tonic-gate 	 *
617c478bd9Sstevel@tonic-gate 	 * Avaialble MSIQs and its properties.
627c478bd9Sstevel@tonic-gate 	 */
6326947304SEvan Yan 	if (px_msiq_get_props(px_p) != DDI_SUCCESS)
6426947304SEvan Yan 		return (DDI_FAILURE);
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	/*
677c478bd9Sstevel@tonic-gate 	 * 10% of available MSIQs are reserved for the PCIe messages.
687c478bd9Sstevel@tonic-gate 	 * Around 90% of available MSIQs are reserved for the MSI/Xs.
697c478bd9Sstevel@tonic-gate 	 */
707c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_msg_qcnt = howmany(msiq_state_p->msiq_cnt, 10);
7118191143SAlan Adamson, SD OSSD 
7218191143SAlan Adamson, SD OSSD 	qcnt = MIN(msiq_state_p->msiq_msg_qcnt, px_max_msiq_msgs);
7318191143SAlan Adamson, SD OSSD 	msiq_state_p->msiq_msg_qcnt = qcnt = MAX(qcnt, px_min_msiq_msgs);
7418191143SAlan Adamson, SD OSSD 	msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - qcnt;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id;
777c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_1st_msg_qid = msiq_state_p->msiq_1st_msiq_id +
787c478bd9Sstevel@tonic-gate 	    msiq_state_p->msiq_msi_qcnt;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt *
817c478bd9Sstevel@tonic-gate 	    sizeof (px_msiq_t), KM_SLEEP);
827c478bd9Sstevel@tonic-gate 
83*d17daf0bSScott Carter, SD IOSW 	mutex_enter(&ib_p->ib_ino_lst_mutex);
847c478bd9Sstevel@tonic-gate 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
857c478bd9Sstevel@tonic-gate 		msiq_state_p->msiq_p[i].msiq_id =
867c478bd9Sstevel@tonic-gate 		    msiq_state_p->msiq_1st_msiq_id + i;
87b0fc0e77Sgovinda 		msiq_state_p->msiq_p[i].msiq_refcnt = 0;
887c478bd9Sstevel@tonic-gate 		msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE;
8909b1eac2SEvan Yan 		(void) px_ib_alloc_ino(ib_p, px_msiqid_to_devino(px_p,
9009b1eac2SEvan Yan 		    msiq_state_p->msiq_p[i].msiq_id));
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
93*d17daf0bSScott Carter, SD IOSW 	msiq_state_p->msiq_redist_flag = B_TRUE;
94*d17daf0bSScott Carter, SD IOSW 	mutex_exit(&ib_p->ib_ino_lst_mutex);
95*d17daf0bSScott Carter, SD IOSW 
967c478bd9Sstevel@tonic-gate 	if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS)
977c478bd9Sstevel@tonic-gate 		px_msiq_detach(px_p);
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	return (ret);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * px_msiq_detach()
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate void
px_msiq_detach(px_t * px_p)1067c478bd9Sstevel@tonic-gate px_msiq_detach(px_t *px_p)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n");
1117c478bd9Sstevel@tonic-gate 
112d8d130aeSanbui 	if (px_lib_msiq_fini(px_p->px_dip) != DDI_SUCCESS) {
113d8d130aeSanbui 		DBG(DBG_MSIQ, px_p->px_dip,
114d8d130aeSanbui 		    "px_lib_msiq_fini: failed\n");
115d8d130aeSanbui 	}
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	kmem_free(msiq_state_p->msiq_p,
1187c478bd9Sstevel@tonic-gate 	    msiq_state_p->msiq_cnt * sizeof (px_msiq_t));
1197c478bd9Sstevel@tonic-gate 
12009b1eac2SEvan Yan 	bzero(msiq_state_p, sizeof (px_msiq_state_t));
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
123023ccc1eSegillett /*
12409b1eac2SEvan Yan  * px_msiq_resume()
125023ccc1eSegillett  */
126023ccc1eSegillett void
px_msiq_resume(px_t * px_p)127023ccc1eSegillett px_msiq_resume(px_t *px_p)
128023ccc1eSegillett {
129b0fc0e77Sgovinda 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
130023ccc1eSegillett 	int		i;
131023ccc1eSegillett 
132b0fc0e77Sgovinda 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
13309b1eac2SEvan Yan 		(void) px_lib_msiq_gethead(px_p->px_dip,
13409b1eac2SEvan Yan 		    msiq_state_p->msiq_p[i].msiq_id,
135b0fc0e77Sgovinda 		    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
136b0fc0e77Sgovinda 		msiq_state_p->msiq_p[i].msiq_new_head_index = 0;
137b0fc0e77Sgovinda 		msiq_state_p->msiq_p[i].msiq_recs2process = 0;
138b0fc0e77Sgovinda 	}
139023ccc1eSegillett }
140023ccc1eSegillett 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * px_msiq_alloc()
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@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)14518191143SAlan Adamson, SD OSSD px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msgcode_t msg_code,
14618191143SAlan Adamson, SD OSSD     msiqid_t *msiq_id_p)
1477c478bd9Sstevel@tonic-gate {
14809b1eac2SEvan Yan 	px_ib_t		*ib_p = px_p->px_ib_p;
14909b1eac2SEvan Yan 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
15009b1eac2SEvan Yan 	msiqid_t	first_msiq_id;
1517c478bd9Sstevel@tonic-gate 	uint_t		msiq_cnt;
15209b1eac2SEvan Yan 	ushort_t	least_refcnt;
1537c478bd9Sstevel@tonic-gate 	int		i;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n");
1567c478bd9Sstevel@tonic-gate 
15709b1eac2SEvan Yan 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	if (rec_type == MSG_REC) {
16018191143SAlan Adamson, SD OSSD 		/*
16118191143SAlan Adamson, SD OSSD 		 * The first MSG EQ is dedicated to PCIE_MSG_CODE_ERR_COR
16218191143SAlan Adamson, SD OSSD 		 * messages. All other messages will be spread across
16318191143SAlan Adamson, SD OSSD 		 * the remaining MSG EQs.
16418191143SAlan Adamson, SD OSSD 		 */
1657c478bd9Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
16618191143SAlan Adamson, SD OSSD 
16718191143SAlan Adamson, SD OSSD 		if (msg_code == PCIE_MSG_CODE_ERR_COR) {
16818191143SAlan Adamson, SD OSSD 			msiq_state_p->msiq_p[first_msiq_id].msiq_state =
16918191143SAlan Adamson, SD OSSD 			    MSIQ_STATE_INUSE;
17018191143SAlan Adamson, SD OSSD 
17118191143SAlan Adamson, SD OSSD 			(void) px_lib_msiq_gethead(px_p->px_dip, first_msiq_id,
17218191143SAlan Adamson, SD OSSD 			    &msiq_state_p->msiq_p[first_msiq_id].
17318191143SAlan Adamson, SD OSSD 			    msiq_curr_head_index);
17418191143SAlan Adamson, SD OSSD 
17518191143SAlan Adamson, SD OSSD 			*msiq_id_p =
17618191143SAlan Adamson, SD OSSD 			    msiq_state_p->msiq_p[first_msiq_id].msiq_id;
17718191143SAlan Adamson, SD OSSD 
17818191143SAlan Adamson, SD OSSD 			msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt++;
17918191143SAlan Adamson, SD OSSD 
18018191143SAlan Adamson, SD OSSD 			DBG(DBG_MSIQ, px_p->px_dip,
18118191143SAlan Adamson, SD OSSD 			    "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
18218191143SAlan Adamson, SD OSSD 
18318191143SAlan Adamson, SD OSSD 			return (DDI_SUCCESS);
18418191143SAlan Adamson, SD OSSD 		}
18518191143SAlan Adamson, SD OSSD 
18618191143SAlan Adamson, SD OSSD 		/* Jump past the first/dedicated EQ */
18718191143SAlan Adamson, SD OSSD 		first_msiq_id++;
18818191143SAlan Adamson, SD OSSD 		msiq_cnt = msiq_state_p->msiq_msg_qcnt - 1;
1897c478bd9Sstevel@tonic-gate 	} else {
1907c478bd9Sstevel@tonic-gate 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
1917c478bd9Sstevel@tonic-gate 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 
19409b1eac2SEvan Yan 	*msiq_id_p = first_msiq_id;
19509b1eac2SEvan Yan 	least_refcnt = msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt;
19609b1eac2SEvan Yan 
1977c478bd9Sstevel@tonic-gate 	/* Allocate MSIQs */
1987c478bd9Sstevel@tonic-gate 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
1997c478bd9Sstevel@tonic-gate 		if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) {
2007c478bd9Sstevel@tonic-gate 			msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE;
2012419d3ccSegillett 			(void) px_lib_msiq_gethead(px_p->px_dip, i,
2022419d3ccSegillett 			    &msiq_state_p->msiq_p[i].msiq_curr_head_index);
20309b1eac2SEvan Yan 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
2047c478bd9Sstevel@tonic-gate 			break;
2057c478bd9Sstevel@tonic-gate 		}
2067c478bd9Sstevel@tonic-gate 
20709b1eac2SEvan Yan 		if (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt) {
20809b1eac2SEvan Yan 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
20909b1eac2SEvan Yan 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
21009b1eac2SEvan Yan 		}
211b0fc0e77Sgovinda 	}
2127c478bd9Sstevel@tonic-gate 
21309b1eac2SEvan Yan 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
21409b1eac2SEvan Yan 
2157c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip,
2167c478bd9Sstevel@tonic-gate 	    "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
2177c478bd9Sstevel@tonic-gate 
21809b1eac2SEvan Yan 	return (DDI_SUCCESS);
21909b1eac2SEvan Yan }
22009b1eac2SEvan Yan 
22109b1eac2SEvan Yan /*
22209b1eac2SEvan Yan  * px_msiq_alloc_based_on_cpuid()
22309b1eac2SEvan Yan  */
22409b1eac2SEvan Yan 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)22509b1eac2SEvan Yan px_msiq_alloc_based_on_cpuid(px_t *px_p, msiq_rec_type_t rec_type,
22609b1eac2SEvan Yan     cpuid_t cpuid, msiqid_t *msiq_id_p)
22709b1eac2SEvan Yan {
22809b1eac2SEvan Yan 	px_ib_t		*ib_p = px_p->px_ib_p;
22909b1eac2SEvan Yan 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
23009b1eac2SEvan Yan 	msiqid_t	first_msiq_id, free_msiq_id;
23109b1eac2SEvan Yan 	uint_t		msiq_cnt;
23209b1eac2SEvan Yan 	ushort_t	least_refcnt;
23309b1eac2SEvan Yan 	px_ino_t	*ino_p;
23409b1eac2SEvan Yan 	int		i;
23509b1eac2SEvan Yan 
23609b1eac2SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc_based_on_cpuid: "
23709b1eac2SEvan Yan 	    "cpuid 0x%x\n", cpuid);
23809b1eac2SEvan Yan 
23909b1eac2SEvan Yan 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
24009b1eac2SEvan Yan 
24109b1eac2SEvan Yan 	if (rec_type == MSG_REC) {
24209b1eac2SEvan Yan 		msiq_cnt = msiq_state_p->msiq_msg_qcnt;
24309b1eac2SEvan Yan 		first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
24409b1eac2SEvan Yan 	} else {
24509b1eac2SEvan Yan 		msiq_cnt = msiq_state_p->msiq_msi_qcnt;
24609b1eac2SEvan Yan 		first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
24709b1eac2SEvan Yan 	}
24809b1eac2SEvan Yan 
24909b1eac2SEvan Yan 	*msiq_id_p = free_msiq_id = (msiqid_t)-1;
25009b1eac2SEvan Yan 	least_refcnt = (ushort_t)-1;
2517c478bd9Sstevel@tonic-gate 
25209b1eac2SEvan Yan 	/* Allocate MSIQs */
25309b1eac2SEvan Yan 	for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
25409b1eac2SEvan Yan 		ino_p = px_ib_locate_ino(ib_p, px_msiqid_to_devino(px_p, i));
25509b1eac2SEvan Yan 
25609b1eac2SEvan Yan 		if ((ino_p->ino_cpuid == cpuid) &&
25709b1eac2SEvan Yan 		    (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt)) {
25809b1eac2SEvan Yan 			*msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
25909b1eac2SEvan Yan 			least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt;
26009b1eac2SEvan Yan 		}
26109b1eac2SEvan Yan 
26209b1eac2SEvan Yan 		if ((*msiq_id_p == -1) && (free_msiq_id == -1) &&
26309b1eac2SEvan Yan 		    (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE))
26409b1eac2SEvan Yan 			free_msiq_id = msiq_state_p->msiq_p[i].msiq_id;
26509b1eac2SEvan Yan 	}
26609b1eac2SEvan Yan 
26709b1eac2SEvan Yan 	if (*msiq_id_p == -1) {
26809b1eac2SEvan Yan 		if (free_msiq_id == -1) {
26909b1eac2SEvan Yan 			DBG(DBG_MSIQ, px_p->px_dip,
27009b1eac2SEvan Yan 			    "px_msiq_alloc_based_on_cpuid: No EQ is available "
27109b1eac2SEvan Yan 			    "for CPU 0x%x\n", cpuid);
27209b1eac2SEvan Yan 			return (DDI_EINVAL);
27309b1eac2SEvan Yan 		}
27409b1eac2SEvan Yan 
27509b1eac2SEvan Yan 		*msiq_id_p = free_msiq_id;
27609b1eac2SEvan Yan 		ino_p = px_ib_locate_ino(ib_p,
27709b1eac2SEvan Yan 		    px_msiqid_to_devino(px_p, *msiq_id_p));
27809b1eac2SEvan Yan 		ino_p->ino_cpuid = ino_p->ino_default_cpuid = cpuid;
27909b1eac2SEvan Yan 	}
28009b1eac2SEvan Yan 
28109b1eac2SEvan Yan 	if (msiq_state_p->msiq_p[*msiq_id_p].msiq_state == MSIQ_STATE_FREE) {
28209b1eac2SEvan Yan 		msiq_state_p->msiq_p[*msiq_id_p].msiq_state = MSIQ_STATE_INUSE;
28309b1eac2SEvan Yan 		(void) px_lib_msiq_gethead(px_p->px_dip, *msiq_id_p,
28409b1eac2SEvan Yan 		    &msiq_state_p->msiq_p[*msiq_id_p].msiq_curr_head_index);
28509b1eac2SEvan Yan 	}
28609b1eac2SEvan Yan 
28709b1eac2SEvan Yan 	msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
28809b1eac2SEvan Yan 
28909b1eac2SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip,
29009b1eac2SEvan Yan 	    "px_msiq_alloc_based_on_cpuid: msiq_id 0x%x\n", *msiq_id_p);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate  * px_msiq_free()
2977c478bd9Sstevel@tonic-gate  */
2987c478bd9Sstevel@tonic-gate int
px_msiq_free(px_t * px_p,msiqid_t msiq_id)2997c478bd9Sstevel@tonic-gate px_msiq_free(px_t *px_p, msiqid_t msiq_id)
3007c478bd9Sstevel@tonic-gate {
30109b1eac2SEvan Yan 	px_ib_t		*ib_p = px_p->px_ib_p;
30209b1eac2SEvan Yan 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id);
3057c478bd9Sstevel@tonic-gate 
30609b1eac2SEvan Yan 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
3077c478bd9Sstevel@tonic-gate 
308b0fc0e77Sgovinda 	if ((msiq_id < msiq_state_p->msiq_1st_msiq_id) || (msiq_id >=
309b0fc0e77Sgovinda 	    (msiq_state_p->msiq_1st_msiq_id + msiq_state_p->msiq_cnt))) {
3107c478bd9Sstevel@tonic-gate 		DBG(DBG_MSIQ, px_p->px_dip,
3117c478bd9Sstevel@tonic-gate 		    "px_msiq_free: Invalid msiq_id 0x%x", msiq_id);
312b0fc0e77Sgovinda 		return (DDI_FAILURE);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
315b0fc0e77Sgovinda 	if (--msiq_state_p->msiq_p[msiq_id].msiq_refcnt == 0)
316b0fc0e77Sgovinda 		msiq_state_p->msiq_p[msiq_id].msiq_state = MSIQ_STATE_FREE;
317b0fc0e77Sgovinda 
318b0fc0e77Sgovinda 	return (DDI_SUCCESS);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
32109b1eac2SEvan Yan /*
32209b1eac2SEvan Yan  * px_msiq_redist()
32309b1eac2SEvan Yan  */
32409b1eac2SEvan Yan void
px_msiq_redist(px_t * px_p)32509b1eac2SEvan Yan px_msiq_redist(px_t *px_p)
32609b1eac2SEvan Yan {
32709b1eac2SEvan Yan 	px_ib_t		*ib_p = px_p->px_ib_p;
32809b1eac2SEvan Yan 	px_msiq_state_t	*msiq_state_p = &ib_p->ib_msiq_state;
32909b1eac2SEvan Yan 	px_ino_t	*ino_p;
33009b1eac2SEvan Yan 	int		i;
33109b1eac2SEvan Yan 
33209b1eac2SEvan Yan 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
33309b1eac2SEvan Yan 
334*d17daf0bSScott Carter, SD IOSW 	if (msiq_state_p->msiq_redist_flag == B_FALSE)
33509b1eac2SEvan Yan 		return;
33609b1eac2SEvan Yan 
33709b1eac2SEvan Yan 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
33809b1eac2SEvan Yan 		ino_p = px_ib_locate_ino(ib_p,
33909b1eac2SEvan Yan 		    px_msiqid_to_devino(px_p, msiq_state_p->msiq_p[i].msiq_id));
34009b1eac2SEvan Yan 
34109b1eac2SEvan Yan 		if (ino_p) {
34209b1eac2SEvan Yan 			ino_p->ino_cpuid = ino_p->ino_default_cpuid =
34309b1eac2SEvan Yan 			    intr_dist_cpuid();
34409b1eac2SEvan Yan 
34509b1eac2SEvan Yan 			DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_redist: "
34609b1eac2SEvan Yan 			    "sysino 0x%llx current cpuid 0x%x "
34709b1eac2SEvan Yan 			    "default cpuid 0x%x\n", ino_p->ino_sysino,
34809b1eac2SEvan Yan 			    ino_p->ino_cpuid, ino_p->ino_default_cpuid);
34909b1eac2SEvan Yan 		}
35009b1eac2SEvan Yan 	}
35109b1eac2SEvan Yan 
35209b1eac2SEvan Yan 	msiq_state_p->msiq_redist_flag = B_FALSE;
35309b1eac2SEvan Yan }
35409b1eac2SEvan Yan 
3557c478bd9Sstevel@tonic-gate /*
3567c478bd9Sstevel@tonic-gate  * px_msiqid_to_devino()
3577c478bd9Sstevel@tonic-gate  */
3587c478bd9Sstevel@tonic-gate devino_t
px_msiqid_to_devino(px_t * px_p,msiqid_t msiq_id)3597c478bd9Sstevel@tonic-gate px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3627c478bd9Sstevel@tonic-gate 	devino_t	devino;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	devino = msiq_state_p->msiq_1st_devino +
3657c478bd9Sstevel@tonic-gate 	    msiq_id - msiq_state_p->msiq_1st_msiq_id;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: "
3687c478bd9Sstevel@tonic-gate 	    "msiq_id 0x%x devino 0x%x\n", msiq_id, devino);
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	return (devino);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate  * px_devino_to_msiqid()
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate msiqid_t
px_devino_to_msiqid(px_t * px_p,devino_t devino)3777c478bd9Sstevel@tonic-gate px_devino_to_msiqid(px_t *px_p, devino_t devino)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3807c478bd9Sstevel@tonic-gate 	msiqid_t	msiq_id;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	msiq_id = msiq_state_p->msiq_1st_msiq_id +
3837c478bd9Sstevel@tonic-gate 	    devino - msiq_state_p->msiq_1st_devino;
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: "
3867c478bd9Sstevel@tonic-gate 	    "devino 0x%x msiq_id 0x%x\n", devino, msiq_id);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	return (msiq_id);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate  * px_msiq_get_props()
3937c478bd9Sstevel@tonic-gate  */
39426947304SEvan Yan static int
px_msiq_get_props(px_t * px_p)3957c478bd9Sstevel@tonic-gate px_msiq_get_props(px_t *px_p)
3967c478bd9Sstevel@tonic-gate {
39726947304SEvan Yan 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
39826947304SEvan Yan 	int		length = sizeof (int);
39926947304SEvan Yan 	char		*valuep = NULL;
40026947304SEvan Yan 	int		ret;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n");
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/* #msi-eqs */
4057c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
40626947304SEvan Yan 	    DDI_PROP_DONTPASS, "#msi-eqs", 0);
4077c478bd9Sstevel@tonic-gate 
40826947304SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_cnt=%d\n", msiq_state_p->msiq_cnt);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/* msi-eq-size */
4117c478bd9Sstevel@tonic-gate 	msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip,
41226947304SEvan Yan 	    DDI_PROP_DONTPASS, "msi-eq-size", 0);
4137c478bd9Sstevel@tonic-gate 
41426947304SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_rec_cnt=%d\n",
4157c478bd9Sstevel@tonic-gate 	    msiq_state_p->msiq_rec_cnt);
4167c478bd9Sstevel@tonic-gate 
41726947304SEvan Yan 	if ((msiq_state_p->msiq_cnt == 0) || (msiq_state_p->msiq_rec_cnt == 0))
41826947304SEvan Yan 		return (DDI_FAILURE);
41926947304SEvan Yan 
4207c478bd9Sstevel@tonic-gate 	/* msi-eq-to-devino: msi-eq#, devino# fields */
4217c478bd9Sstevel@tonic-gate 	ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC,
42226947304SEvan Yan 	    DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, &length);
42326947304SEvan Yan 
42426947304SEvan Yan 	/*
42526947304SEvan Yan 	 * NOTE:
42626947304SEvan Yan 	 * On sun4u PCIe systems, the msi-eq-to-devino property is broken and
42726947304SEvan Yan 	 * these systems defines this property as msi-eq-devino.
42826947304SEvan Yan 	 */
42926947304SEvan Yan 	if (ret == DDI_PROP_NOT_FOUND) {
43026947304SEvan Yan 		DBG(DBG_MSIQ, px_p->px_dip, "msi-eq-to-devino is not found\n");
43126947304SEvan Yan 		ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip,
43226947304SEvan Yan 		    PROP_LEN_AND_VAL_ALLOC, DDI_PROP_DONTPASS, "msi-eq-devino",
43326947304SEvan Yan 		    (caddr_t)&valuep, &length);
43426947304SEvan Yan 	}
43526947304SEvan Yan 
43626947304SEvan Yan 	if (ret != DDI_PROP_SUCCESS) {
43726947304SEvan Yan 		return (DDI_FAILURE);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
44026947304SEvan Yan 	msiq_state_p->msiq_1st_msiq_id =
44126947304SEvan Yan 	    ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no;
44226947304SEvan Yan 	msiq_state_p->msiq_1st_devino =
44326947304SEvan Yan 	    ((px_msi_eq_to_devino_t *)valuep)->devino_no;
44426947304SEvan Yan 
44526947304SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_msiq_id=%d\n",
4467c478bd9Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_msiq_id);
4477c478bd9Sstevel@tonic-gate 
44826947304SEvan Yan 	DBG(DBG_MSIQ, px_p->px_dip, "msiq_1st_devino=%d\n",
4497c478bd9Sstevel@tonic-gate 	    msiq_state_p->msiq_1st_devino);
45026947304SEvan Yan 
45126947304SEvan Yan 	kmem_free(valuep, (size_t)length);
45226947304SEvan Yan 	return (DDI_SUCCESS);
4537c478bd9Sstevel@tonic-gate }
454