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
1237c478bd9Sstevel@tonic-gate /*
12409b1eac2SEvan Yan * px_msiq_resume()
125023ccc1eSegillett */
126023ccc1eSegillett void
px_msiq_resume(px_t * px_p)127023ccc1eSegillett px_msiq_resume(px_t *px_p)
128023ccc1eSegillett {
129023ccc1eSegillett 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
141023ccc1eSegillett /*
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));
15809b1eac2SEvan Yan
15909b1eac2SEvan Yan 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 */
16509b1eac2SEvan Yan 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;
18909b1eac2SEvan Yan } else {
19009b1eac2SEvan Yan msiq_cnt = msiq_state_p->msiq_msi_qcnt;
19109b1eac2SEvan Yan first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
19209b1eac2SEvan Yan }
19309b1eac2SEvan Yan
19409b1eac2SEvan Yan *msiq_id_p = first_msiq_id;
19509b1eac2SEvan Yan least_refcnt = msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt;
19609b1eac2SEvan Yan
19709b1eac2SEvan Yan /* Allocate MSIQs */
19809b1eac2SEvan Yan for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) {
19909b1eac2SEvan Yan if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) {
20009b1eac2SEvan Yan msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE;
20109b1eac2SEvan Yan (void) px_lib_msiq_gethead(px_p->px_dip, i,
20209b1eac2SEvan Yan &msiq_state_p->msiq_p[i].msiq_curr_head_index);
20309b1eac2SEvan Yan *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id;
20409b1eac2SEvan Yan break;
20509b1eac2SEvan Yan }
20609b1eac2SEvan Yan
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 }
21109b1eac2SEvan Yan }
21209b1eac2SEvan Yan
21309b1eac2SEvan Yan msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++;
21409b1eac2SEvan Yan
21509b1eac2SEvan Yan DBG(DBG_MSIQ, px_p->px_dip,
21609b1eac2SEvan Yan "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p);
21709b1eac2SEvan Yan
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
2417c478bd9Sstevel@tonic-gate if (rec_type == MSG_REC) {
2427c478bd9Sstevel@tonic-gate msiq_cnt = msiq_state_p->msiq_msg_qcnt;
2437c478bd9Sstevel@tonic-gate first_msiq_id = msiq_state_p->msiq_1st_msg_qid;
2447c478bd9Sstevel@tonic-gate } else {
2457c478bd9Sstevel@tonic-gate msiq_cnt = msiq_state_p->msiq_msi_qcnt;
2467c478bd9Sstevel@tonic-gate first_msiq_id = msiq_state_p->msiq_1st_msi_qid;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
24909b1eac2SEvan Yan *msiq_id_p = free_msiq_id = (msiqid_t)-1;
25009b1eac2SEvan Yan least_refcnt = (ushort_t)-1;
25109b1eac2SEvan Yan
2527c478bd9Sstevel@tonic-gate /* Allocate MSIQs */
2537c478bd9Sstevel@tonic-gate 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));
2557c478bd9Sstevel@tonic-gate
25609b1eac2SEvan Yan if ((ino_p->ino_cpuid == cpuid) &&
25709b1eac2SEvan Yan (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt)) {
2587c478bd9Sstevel@tonic-gate *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) {
2697c478bd9Sstevel@tonic-gate 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 }
2747c478bd9Sstevel@tonic-gate
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
3217c478bd9Sstevel@tonic-gate /*
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
35509b1eac2SEvan Yan /*
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 {
3977c478bd9Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
3987c478bd9Sstevel@tonic-gate int length = sizeof (int);
3997c478bd9Sstevel@tonic-gate 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);
4237c478bd9Sstevel@tonic-gate
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);
43826947304SEvan Yan }
43926947304SEvan Yan
4407c478bd9Sstevel@tonic-gate msiq_state_p->msiq_1st_msiq_id =
4417c478bd9Sstevel@tonic-gate ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no;
4427c478bd9Sstevel@tonic-gate msiq_state_p->msiq_1st_devino =
4437c478bd9Sstevel@tonic-gate ((px_msi_eq_to_devino_t *)valuep)->devino_no;
4447c478bd9Sstevel@tonic-gate
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