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 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 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 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 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 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 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 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 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 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 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