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