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 5*2588Segillett * Common Development and Distribution License (the "License"). 6*2588Segillett * 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*2588Segillett * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * px_msiq.c 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <sys/types.h> 330Sstevel@tonic-gate #include <sys/kmem.h> 340Sstevel@tonic-gate #include <sys/conf.h> 350Sstevel@tonic-gate #include <sys/ddi.h> 360Sstevel@tonic-gate #include <sys/sunddi.h> 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 430Sstevel@tonic-gate static void 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 { 510Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 520Sstevel@tonic-gate caddr_t msiq_addr; 530Sstevel@tonic-gate size_t msiq_size; 540Sstevel@tonic-gate int i, ret = DDI_SUCCESS; 550Sstevel@tonic-gate 560Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n"); 570Sstevel@tonic-gate 580Sstevel@tonic-gate /* 590Sstevel@tonic-gate * Check for all MSIQ related properties and 600Sstevel@tonic-gate * save all information. 610Sstevel@tonic-gate * 620Sstevel@tonic-gate * Avaialble MSIQs and its properties. 630Sstevel@tonic-gate */ 640Sstevel@tonic-gate px_msiq_get_props(px_p); 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); 710Sstevel@tonic-gate msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - 720Sstevel@tonic-gate msiq_state_p->msiq_msg_qcnt; 730Sstevel@tonic-gate 740Sstevel@tonic-gate msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id; 750Sstevel@tonic-gate msiq_state_p->msiq_next_msi_qid = msiq_state_p->msiq_1st_msi_qid; 760Sstevel@tonic-gate 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 msiq_state_p->msiq_next_msg_qid = msiq_state_p->msiq_1st_msg_qid; 800Sstevel@tonic-gate 810Sstevel@tonic-gate mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL); 820Sstevel@tonic-gate msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt * 830Sstevel@tonic-gate sizeof (px_msiq_t), KM_SLEEP); 840Sstevel@tonic-gate 850Sstevel@tonic-gate msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); 860Sstevel@tonic-gate msiq_state_p->msiq_buf_p = kmem_zalloc(msiq_state_p->msiq_cnt * 870Sstevel@tonic-gate msiq_size, KM_SLEEP); 880Sstevel@tonic-gate 890Sstevel@tonic-gate msiq_addr = (caddr_t)(((uint64_t)msiq_state_p->msiq_buf_p + 900Sstevel@tonic-gate (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); 910Sstevel@tonic-gate 920Sstevel@tonic-gate for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 930Sstevel@tonic-gate msiq_state_p->msiq_p[i].msiq_id = 940Sstevel@tonic-gate msiq_state_p->msiq_1st_msiq_id + i; 950Sstevel@tonic-gate msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 960Sstevel@tonic-gate 97*2588Segillett msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *) 980Sstevel@tonic-gate ((caddr_t)msiq_addr + (i * msiq_size)); 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) 1020Sstevel@tonic-gate px_msiq_detach(px_p); 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate return (ret); 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * px_msiq_detach() 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate void 1110Sstevel@tonic-gate px_msiq_detach(px_t *px_p) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n"); 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate (void) px_lib_msiq_fini(px_p->px_dip); 1180Sstevel@tonic-gate kmem_free(msiq_state_p->msiq_buf_p, msiq_state_p->msiq_cnt * 1190Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t)); 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate mutex_destroy(&msiq_state_p->msiq_mutex); 1220Sstevel@tonic-gate kmem_free(msiq_state_p->msiq_p, 1230Sstevel@tonic-gate msiq_state_p->msiq_cnt * sizeof (px_msiq_t)); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate bzero(&px_p->px_ib_p->ib_msiq_state, sizeof (px_msiq_state_t)); 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 129*2588Segillett * px_msiq_resume() 130*2588Segillett */ 131*2588Segillett void 132*2588Segillett px_msiq_resume(px_t *px_p) 133*2588Segillett { 134*2588Segillett px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 135*2588Segillett int i; 136*2588Segillett 137*2588Segillett for (i = 0; i < msiq_state_p->msiq_cnt; i++) 138*2588Segillett (void) px_lib_msiq_gethead(px_p->px_dip, i, 139*2588Segillett &msiq_state_p->msiq_p[i].msiq_curr_head_idx); 140*2588Segillett } 141*2588Segillett 142*2588Segillett /* 1430Sstevel@tonic-gate * px_msiq_alloc() 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate int 1460Sstevel@tonic-gate px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msiqid_t *msiq_id_p) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 1490Sstevel@tonic-gate msiqid_t first_msiq_id, *next_msiq_index; 1500Sstevel@tonic-gate uint_t msiq_cnt; 1510Sstevel@tonic-gate int i; 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n"); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate mutex_enter(&msiq_state_p->msiq_mutex); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (rec_type == MSG_REC) { 1580Sstevel@tonic-gate msiq_cnt = msiq_state_p->msiq_msg_qcnt; 1590Sstevel@tonic-gate first_msiq_id = msiq_state_p->msiq_1st_msg_qid; 1600Sstevel@tonic-gate next_msiq_index = &msiq_state_p->msiq_next_msg_qid; 1610Sstevel@tonic-gate } else { 1620Sstevel@tonic-gate msiq_cnt = msiq_state_p->msiq_msi_qcnt; 1630Sstevel@tonic-gate first_msiq_id = msiq_state_p->msiq_1st_msi_qid; 1640Sstevel@tonic-gate next_msiq_index = &msiq_state_p->msiq_next_msi_qid; 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* Allocate MSIQs */ 1680Sstevel@tonic-gate for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) { 1690Sstevel@tonic-gate if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) { 1700Sstevel@tonic-gate msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE; 1710Sstevel@tonic-gate break; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * There are no free MSIQ. 1770Sstevel@tonic-gate * Use next available MSIQ. 1780Sstevel@tonic-gate */ 1790Sstevel@tonic-gate if (i >= (first_msiq_id + msiq_cnt)) 1800Sstevel@tonic-gate i = *next_msiq_index; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 1830Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, 1840Sstevel@tonic-gate "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate (*next_msiq_index)++; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate if (*next_msiq_index >= (first_msiq_id + msiq_cnt)) 1890Sstevel@tonic-gate *next_msiq_index = first_msiq_id; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate mutex_exit(&msiq_state_p->msiq_mutex); 1920Sstevel@tonic-gate return (DDI_SUCCESS); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * px_msiq_free() 1970Sstevel@tonic-gate */ 1980Sstevel@tonic-gate int 1990Sstevel@tonic-gate px_msiq_free(px_t *px_p, msiqid_t msiq_id) 2000Sstevel@tonic-gate { 2010Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 2020Sstevel@tonic-gate int i, ret = DDI_SUCCESS; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate mutex_enter(&msiq_state_p->msiq_mutex); 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 2090Sstevel@tonic-gate if (msiq_state_p->msiq_p[i].msiq_id == msiq_id) { 2100Sstevel@tonic-gate msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 211*2588Segillett msiq_state_p->msiq_p[i].msiq_curr_head_idx = 0; 2120Sstevel@tonic-gate break; 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate if (i >= msiq_state_p->msiq_cnt) { 2170Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, 2180Sstevel@tonic-gate "px_msiq_free: Invalid msiq_id 0x%x", msiq_id); 2190Sstevel@tonic-gate ret = DDI_FAILURE; 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate mutex_exit(&msiq_state_p->msiq_mutex); 2230Sstevel@tonic-gate return (ret); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * px_msiqid_to_devino() 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate devino_t 2300Sstevel@tonic-gate px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id) 2310Sstevel@tonic-gate { 2320Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 2330Sstevel@tonic-gate devino_t devino; 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate devino = msiq_state_p->msiq_1st_devino + 2360Sstevel@tonic-gate msiq_id - msiq_state_p->msiq_1st_msiq_id; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: " 2390Sstevel@tonic-gate "msiq_id 0x%x devino 0x%x\n", msiq_id, devino); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate return (devino); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * px_devino_to_msiqid() 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate msiqid_t 2480Sstevel@tonic-gate px_devino_to_msiqid(px_t *px_p, devino_t devino) 2490Sstevel@tonic-gate { 2500Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 2510Sstevel@tonic-gate msiqid_t msiq_id; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate msiq_id = msiq_state_p->msiq_1st_msiq_id + 2540Sstevel@tonic-gate devino - msiq_state_p->msiq_1st_devino; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: " 2570Sstevel@tonic-gate "devino 0x%x msiq_id 0x%x\n", devino, msiq_id); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate return (msiq_id); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* 2630Sstevel@tonic-gate * px_msiq_get_props() 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate static void 2660Sstevel@tonic-gate px_msiq_get_props(px_t *px_p) 2670Sstevel@tonic-gate { 2680Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 2690Sstevel@tonic-gate int ret = DDI_SUCCESS; 2700Sstevel@tonic-gate int length = sizeof (int); 2710Sstevel@tonic-gate char *valuep = NULL; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n"); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate /* #msi-eqs */ 2760Sstevel@tonic-gate msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 2770Sstevel@tonic-gate DDI_PROP_DONTPASS, "#msi-eqs", PX_DEFAULT_MSIQ_CNT); 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_cnt=%d\n", 2800Sstevel@tonic-gate msiq_state_p->msiq_cnt); 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate /* msi-eq-size */ 2830Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 2840Sstevel@tonic-gate DDI_PROP_DONTPASS, "msi-eq-size", PX_DEFAULT_MSIQ_REC_CNT); 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_rec_cnt=%d\n", 2870Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* msi-eq-to-devino: msi-eq#, devino# fields */ 2900Sstevel@tonic-gate ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC, 2910Sstevel@tonic-gate DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, 2920Sstevel@tonic-gate &length); 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate if (ret == DDI_PROP_SUCCESS) { 2950Sstevel@tonic-gate msiq_state_p->msiq_1st_msiq_id = 2960Sstevel@tonic-gate ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no; 2970Sstevel@tonic-gate msiq_state_p->msiq_1st_devino = 2980Sstevel@tonic-gate ((px_msi_eq_to_devino_t *)valuep)->devino_no; 2990Sstevel@tonic-gate kmem_free(valuep, (size_t)length); 3000Sstevel@tonic-gate } else { 3010Sstevel@tonic-gate msiq_state_p->msiq_1st_msiq_id = PX_DEFAULT_MSIQ_1ST_MSIQ_ID; 3020Sstevel@tonic-gate msiq_state_p->msiq_1st_devino = PX_DEFAULT_MSIQ_1ST_DEVINO; 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_msiq_id=%d\n", 3060Sstevel@tonic-gate msiq_state_p->msiq_1st_msiq_id); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_devino=%d\n", 3090Sstevel@tonic-gate msiq_state_p->msiq_1st_devino); 3100Sstevel@tonic-gate } 311