1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * px_msiq.c 31 */ 32 33 #include <sys/types.h> 34 #include <sys/kmem.h> 35 #include <sys/conf.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/modctl.h> 39 #include <sys/disp.h> 40 #include <sys/stat.h> 41 #include <sys/ddi_impldefs.h> 42 #include "px_obj.h" 43 44 static void px_msiq_get_props(px_t *px_p); 45 46 /* 47 * px_msiq_attach() 48 */ 49 int 50 px_msiq_attach(px_t *px_p) 51 { 52 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 53 caddr_t msiq_addr; 54 size_t msiq_size; 55 int i, ret = DDI_SUCCESS; 56 57 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n"); 58 59 /* 60 * Check for all MSIQ related properties and 61 * save all information. 62 * 63 * Avaialble MSIQs and its properties. 64 */ 65 px_msiq_get_props(px_p); 66 67 /* 68 * 10% of available MSIQs are reserved for the PCIe messages. 69 * Around 90% of available MSIQs are reserved for the MSI/Xs. 70 */ 71 msiq_state_p->msiq_msg_qcnt = howmany(msiq_state_p->msiq_cnt, 10); 72 msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - 73 msiq_state_p->msiq_msg_qcnt; 74 75 msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id; 76 msiq_state_p->msiq_next_msi_qid = msiq_state_p->msiq_1st_msi_qid; 77 78 msiq_state_p->msiq_1st_msg_qid = msiq_state_p->msiq_1st_msiq_id + 79 msiq_state_p->msiq_msi_qcnt; 80 msiq_state_p->msiq_next_msg_qid = msiq_state_p->msiq_1st_msg_qid; 81 82 mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL); 83 msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt * 84 sizeof (px_msiq_t), KM_SLEEP); 85 86 msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); 87 msiq_state_p->msiq_buf_p = kmem_zalloc(msiq_state_p->msiq_cnt * 88 msiq_size, KM_SLEEP); 89 90 msiq_addr = (caddr_t)(((uint64_t)msiq_state_p->msiq_buf_p + 91 (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); 92 93 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 94 msiq_state_p->msiq_p[i].msiq_id = 95 msiq_state_p->msiq_1st_msiq_id + i; 96 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 97 98 msiq_state_p->msiq_p[i].msiq_base = (uint64_t) 99 ((caddr_t)msiq_addr + (i * msiq_size)); 100 msiq_state_p->msiq_p[i].msiq_curr = 101 msiq_state_p->msiq_p[i].msiq_base; 102 } 103 104 if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) 105 px_msiq_detach(px_p); 106 107 return (ret); 108 } 109 110 /* 111 * px_msiq_detach() 112 */ 113 void 114 px_msiq_detach(px_t *px_p) 115 { 116 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 117 118 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n"); 119 120 (void) px_lib_msiq_fini(px_p->px_dip); 121 kmem_free(msiq_state_p->msiq_buf_p, msiq_state_p->msiq_cnt * 122 msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t)); 123 124 mutex_destroy(&msiq_state_p->msiq_mutex); 125 kmem_free(msiq_state_p->msiq_p, 126 msiq_state_p->msiq_cnt * sizeof (px_msiq_t)); 127 128 bzero(&px_p->px_ib_p->ib_msiq_state, sizeof (px_msiq_state_t)); 129 } 130 131 /* 132 * px_msiq_alloc() 133 */ 134 int 135 px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msiqid_t *msiq_id_p) 136 { 137 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 138 msiqid_t first_msiq_id, *next_msiq_index; 139 uint_t msiq_cnt; 140 int i; 141 142 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n"); 143 144 mutex_enter(&msiq_state_p->msiq_mutex); 145 146 if (rec_type == MSG_REC) { 147 msiq_cnt = msiq_state_p->msiq_msg_qcnt; 148 first_msiq_id = msiq_state_p->msiq_1st_msg_qid; 149 next_msiq_index = &msiq_state_p->msiq_next_msg_qid; 150 } else { 151 msiq_cnt = msiq_state_p->msiq_msi_qcnt; 152 first_msiq_id = msiq_state_p->msiq_1st_msi_qid; 153 next_msiq_index = &msiq_state_p->msiq_next_msi_qid; 154 } 155 156 /* Allocate MSIQs */ 157 for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) { 158 if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) { 159 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE; 160 break; 161 } 162 } 163 164 /* 165 * There are no free MSIQ. 166 * Use next available MSIQ. 167 */ 168 if (i >= (first_msiq_id + msiq_cnt)) 169 i = *next_msiq_index; 170 171 *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 172 DBG(DBG_MSIQ, px_p->px_dip, 173 "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p); 174 175 (*next_msiq_index)++; 176 177 if (*next_msiq_index >= (first_msiq_id + msiq_cnt)) 178 *next_msiq_index = first_msiq_id; 179 180 mutex_exit(&msiq_state_p->msiq_mutex); 181 return (DDI_SUCCESS); 182 } 183 184 /* 185 * px_msiq_free() 186 */ 187 int 188 px_msiq_free(px_t *px_p, msiqid_t msiq_id) 189 { 190 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 191 int i, ret = DDI_SUCCESS; 192 193 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id); 194 195 mutex_enter(&msiq_state_p->msiq_mutex); 196 197 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 198 if (msiq_state_p->msiq_p[i].msiq_id == msiq_id) { 199 msiq_state_p->msiq_p[i].msiq_curr = 200 msiq_state_p->msiq_p[i].msiq_base; 201 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 202 break; 203 } 204 } 205 206 if (i >= msiq_state_p->msiq_cnt) { 207 DBG(DBG_MSIQ, px_p->px_dip, 208 "px_msiq_free: Invalid msiq_id 0x%x", msiq_id); 209 ret = DDI_FAILURE; 210 } 211 212 mutex_exit(&msiq_state_p->msiq_mutex); 213 return (ret); 214 } 215 216 /* 217 * px_msiqid_to_devino() 218 */ 219 devino_t 220 px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id) 221 { 222 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 223 devino_t devino; 224 225 devino = msiq_state_p->msiq_1st_devino + 226 msiq_id - msiq_state_p->msiq_1st_msiq_id; 227 228 DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: " 229 "msiq_id 0x%x devino 0x%x\n", msiq_id, devino); 230 231 return (devino); 232 } 233 234 /* 235 * px_devino_to_msiqid() 236 */ 237 msiqid_t 238 px_devino_to_msiqid(px_t *px_p, devino_t devino) 239 { 240 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 241 msiqid_t msiq_id; 242 243 msiq_id = msiq_state_p->msiq_1st_msiq_id + 244 devino - msiq_state_p->msiq_1st_devino; 245 246 DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: " 247 "devino 0x%x msiq_id 0x%x\n", devino, msiq_id); 248 249 return (msiq_id); 250 } 251 252 /* 253 * px_msiq_get_props() 254 */ 255 static void 256 px_msiq_get_props(px_t *px_p) 257 { 258 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 259 int ret = DDI_SUCCESS; 260 int length = sizeof (int); 261 char *valuep = NULL; 262 263 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n"); 264 265 /* #msi-eqs */ 266 msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 267 DDI_PROP_DONTPASS, "#msi-eqs", PX_DEFAULT_MSIQ_CNT); 268 269 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_cnt=%d\n", 270 msiq_state_p->msiq_cnt); 271 272 /* msi-eq-size */ 273 msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 274 DDI_PROP_DONTPASS, "msi-eq-size", PX_DEFAULT_MSIQ_REC_CNT); 275 276 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_rec_cnt=%d\n", 277 msiq_state_p->msiq_rec_cnt); 278 279 /* msi-eq-to-devino: msi-eq#, devino# fields */ 280 ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC, 281 DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, 282 &length); 283 284 if (ret == DDI_PROP_SUCCESS) { 285 msiq_state_p->msiq_1st_msiq_id = 286 ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no; 287 msiq_state_p->msiq_1st_devino = 288 ((px_msi_eq_to_devino_t *)valuep)->devino_no; 289 kmem_free(valuep, (size_t)length); 290 } else { 291 msiq_state_p->msiq_1st_msiq_id = PX_DEFAULT_MSIQ_1ST_MSIQ_ID; 292 msiq_state_p->msiq_1st_devino = PX_DEFAULT_MSIQ_1ST_DEVINO; 293 } 294 295 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_msiq_id=%d\n", 296 msiq_state_p->msiq_1st_msiq_id); 297 298 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_devino=%d\n", 299 msiq_state_p->msiq_1st_devino); 300 } 301