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