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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * px_msiq.c 28 */ 29 30 #include <sys/types.h> 31 #include <sys/kmem.h> 32 #include <sys/conf.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/machsystm.h> /* intr_dist_add */ 36 #include <sys/modctl.h> 37 #include <sys/disp.h> 38 #include <sys/stat.h> 39 #include <sys/ddi_impldefs.h> 40 #include "px_obj.h" 41 42 static void px_msiq_get_props(px_t *px_p); 43 44 /* 45 * px_msiq_attach() 46 */ 47 int 48 px_msiq_attach(px_t *px_p) 49 { 50 px_ib_t *ib_p = px_p->px_ib_p; 51 px_msiq_state_t *msiq_state_p = &ib_p->ib_msiq_state; 52 int i, ret = DDI_SUCCESS; 53 54 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n"); 55 56 /* 57 * Check for all MSIQ related properties and 58 * save all information. 59 * 60 * Avaialble MSIQs and its properties. 61 */ 62 px_msiq_get_props(px_p); 63 64 /* 65 * 10% of available MSIQs are reserved for the PCIe messages. 66 * Around 90% of available MSIQs are reserved for the MSI/Xs. 67 */ 68 msiq_state_p->msiq_msg_qcnt = howmany(msiq_state_p->msiq_cnt, 10); 69 msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - 70 msiq_state_p->msiq_msg_qcnt; 71 72 msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id; 73 msiq_state_p->msiq_1st_msg_qid = msiq_state_p->msiq_1st_msiq_id + 74 msiq_state_p->msiq_msi_qcnt; 75 76 mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL); 77 msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt * 78 sizeof (px_msiq_t), KM_SLEEP); 79 80 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 81 msiq_state_p->msiq_p[i].msiq_id = 82 msiq_state_p->msiq_1st_msiq_id + i; 83 msiq_state_p->msiq_p[i].msiq_refcnt = 0; 84 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 85 (void) px_ib_alloc_ino(ib_p, px_msiqid_to_devino(px_p, 86 msiq_state_p->msiq_p[i].msiq_id)); 87 } 88 89 if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) 90 px_msiq_detach(px_p); 91 92 msiq_state_p->msiq_redist_flag = B_TRUE; 93 return (ret); 94 } 95 96 /* 97 * px_msiq_detach() 98 */ 99 void 100 px_msiq_detach(px_t *px_p) 101 { 102 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 103 104 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n"); 105 106 if (px_lib_msiq_fini(px_p->px_dip) != DDI_SUCCESS) { 107 DBG(DBG_MSIQ, px_p->px_dip, 108 "px_lib_msiq_fini: failed\n"); 109 } 110 111 mutex_destroy(&msiq_state_p->msiq_mutex); 112 kmem_free(msiq_state_p->msiq_p, 113 msiq_state_p->msiq_cnt * sizeof (px_msiq_t)); 114 115 bzero(msiq_state_p, sizeof (px_msiq_state_t)); 116 } 117 118 /* 119 * px_msiq_resume() 120 */ 121 void 122 px_msiq_resume(px_t *px_p) 123 { 124 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 125 int i; 126 127 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 128 (void) px_lib_msiq_gethead(px_p->px_dip, 129 msiq_state_p->msiq_p[i].msiq_id, 130 &msiq_state_p->msiq_p[i].msiq_curr_head_index); 131 msiq_state_p->msiq_p[i].msiq_new_head_index = 0; 132 msiq_state_p->msiq_p[i].msiq_recs2process = 0; 133 } 134 } 135 136 /* 137 * px_msiq_alloc() 138 */ 139 int 140 px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msiqid_t *msiq_id_p) 141 { 142 px_ib_t *ib_p = px_p->px_ib_p; 143 px_msiq_state_t *msiq_state_p = &ib_p->ib_msiq_state; 144 msiqid_t first_msiq_id; 145 uint_t msiq_cnt; 146 ushort_t least_refcnt; 147 int i; 148 149 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n"); 150 151 ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); 152 mutex_enter(&msiq_state_p->msiq_mutex); 153 154 if (rec_type == MSG_REC) { 155 msiq_cnt = msiq_state_p->msiq_msg_qcnt; 156 first_msiq_id = msiq_state_p->msiq_1st_msg_qid; 157 } else { 158 msiq_cnt = msiq_state_p->msiq_msi_qcnt; 159 first_msiq_id = msiq_state_p->msiq_1st_msi_qid; 160 } 161 162 *msiq_id_p = first_msiq_id; 163 least_refcnt = msiq_state_p->msiq_p[first_msiq_id].msiq_refcnt; 164 165 /* Allocate MSIQs */ 166 for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) { 167 if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) { 168 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE; 169 (void) px_lib_msiq_gethead(px_p->px_dip, i, 170 &msiq_state_p->msiq_p[i].msiq_curr_head_index); 171 *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 172 break; 173 } 174 175 if (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt) { 176 *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 177 least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt; 178 } 179 } 180 181 msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++; 182 183 DBG(DBG_MSIQ, px_p->px_dip, 184 "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p); 185 186 mutex_exit(&msiq_state_p->msiq_mutex); 187 return (DDI_SUCCESS); 188 } 189 190 /* 191 * px_msiq_alloc_based_on_cpuid() 192 */ 193 int 194 px_msiq_alloc_based_on_cpuid(px_t *px_p, msiq_rec_type_t rec_type, 195 cpuid_t cpuid, msiqid_t *msiq_id_p) 196 { 197 px_ib_t *ib_p = px_p->px_ib_p; 198 px_msiq_state_t *msiq_state_p = &ib_p->ib_msiq_state; 199 msiqid_t first_msiq_id, free_msiq_id; 200 uint_t msiq_cnt; 201 ushort_t least_refcnt; 202 px_ino_t *ino_p; 203 int i; 204 205 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc_based_on_cpuid: " 206 "cpuid 0x%x\n", cpuid); 207 208 ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); 209 210 mutex_enter(&msiq_state_p->msiq_mutex); 211 212 if (rec_type == MSG_REC) { 213 msiq_cnt = msiq_state_p->msiq_msg_qcnt; 214 first_msiq_id = msiq_state_p->msiq_1st_msg_qid; 215 } else { 216 msiq_cnt = msiq_state_p->msiq_msi_qcnt; 217 first_msiq_id = msiq_state_p->msiq_1st_msi_qid; 218 } 219 220 *msiq_id_p = free_msiq_id = (msiqid_t)-1; 221 least_refcnt = (ushort_t)-1; 222 223 /* Allocate MSIQs */ 224 for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) { 225 ino_p = px_ib_locate_ino(ib_p, px_msiqid_to_devino(px_p, i)); 226 227 if ((ino_p->ino_cpuid == cpuid) && 228 (least_refcnt > msiq_state_p->msiq_p[i].msiq_refcnt)) { 229 *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 230 least_refcnt = msiq_state_p->msiq_p[i].msiq_refcnt; 231 } 232 233 if ((*msiq_id_p == -1) && (free_msiq_id == -1) && 234 (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE)) 235 free_msiq_id = msiq_state_p->msiq_p[i].msiq_id; 236 } 237 238 if (*msiq_id_p == -1) { 239 if (free_msiq_id == -1) { 240 DBG(DBG_MSIQ, px_p->px_dip, 241 "px_msiq_alloc_based_on_cpuid: No EQ is available " 242 "for CPU 0x%x\n", cpuid); 243 244 mutex_exit(&msiq_state_p->msiq_mutex); 245 return (DDI_EINVAL); 246 } 247 248 *msiq_id_p = free_msiq_id; 249 ino_p = px_ib_locate_ino(ib_p, 250 px_msiqid_to_devino(px_p, *msiq_id_p)); 251 ino_p->ino_cpuid = ino_p->ino_default_cpuid = cpuid; 252 } 253 254 if (msiq_state_p->msiq_p[*msiq_id_p].msiq_state == MSIQ_STATE_FREE) { 255 msiq_state_p->msiq_p[*msiq_id_p].msiq_state = MSIQ_STATE_INUSE; 256 (void) px_lib_msiq_gethead(px_p->px_dip, *msiq_id_p, 257 &msiq_state_p->msiq_p[*msiq_id_p].msiq_curr_head_index); 258 } 259 260 msiq_state_p->msiq_p[*msiq_id_p].msiq_refcnt++; 261 262 DBG(DBG_MSIQ, px_p->px_dip, 263 "px_msiq_alloc_based_on_cpuid: msiq_id 0x%x\n", *msiq_id_p); 264 265 mutex_exit(&msiq_state_p->msiq_mutex); 266 return (DDI_SUCCESS); 267 } 268 269 /* 270 * px_msiq_free() 271 */ 272 int 273 px_msiq_free(px_t *px_p, msiqid_t msiq_id) 274 { 275 px_ib_t *ib_p = px_p->px_ib_p; 276 px_msiq_state_t *msiq_state_p = &ib_p->ib_msiq_state; 277 278 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id); 279 280 ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); 281 mutex_enter(&msiq_state_p->msiq_mutex); 282 283 if ((msiq_id < msiq_state_p->msiq_1st_msiq_id) || (msiq_id >= 284 (msiq_state_p->msiq_1st_msiq_id + msiq_state_p->msiq_cnt))) { 285 DBG(DBG_MSIQ, px_p->px_dip, 286 "px_msiq_free: Invalid msiq_id 0x%x", msiq_id); 287 288 mutex_exit(&msiq_state_p->msiq_mutex); 289 return (DDI_FAILURE); 290 } 291 292 if (--msiq_state_p->msiq_p[msiq_id].msiq_refcnt == 0) 293 msiq_state_p->msiq_p[msiq_id].msiq_state = MSIQ_STATE_FREE; 294 295 mutex_exit(&msiq_state_p->msiq_mutex); 296 return (DDI_SUCCESS); 297 } 298 299 /* 300 * px_msiq_redist() 301 */ 302 void 303 px_msiq_redist(px_t *px_p) 304 { 305 px_ib_t *ib_p = px_p->px_ib_p; 306 px_msiq_state_t *msiq_state_p = &ib_p->ib_msiq_state; 307 px_ino_t *ino_p; 308 int i; 309 310 ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); 311 312 mutex_enter(&msiq_state_p->msiq_mutex); 313 314 if (msiq_state_p->msiq_redist_flag == B_FALSE) { 315 mutex_exit(&msiq_state_p->msiq_mutex); 316 return; 317 } 318 319 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 320 ino_p = px_ib_locate_ino(ib_p, 321 px_msiqid_to_devino(px_p, msiq_state_p->msiq_p[i].msiq_id)); 322 323 if (ino_p) { 324 ino_p->ino_cpuid = ino_p->ino_default_cpuid = 325 intr_dist_cpuid(); 326 327 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_redist: " 328 "sysino 0x%llx current cpuid 0x%x " 329 "default cpuid 0x%x\n", ino_p->ino_sysino, 330 ino_p->ino_cpuid, ino_p->ino_default_cpuid); 331 } 332 } 333 334 msiq_state_p->msiq_redist_flag = B_FALSE; 335 mutex_exit(&msiq_state_p->msiq_mutex); 336 } 337 338 /* 339 * px_msiqid_to_devino() 340 */ 341 devino_t 342 px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id) 343 { 344 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 345 devino_t devino; 346 347 devino = msiq_state_p->msiq_1st_devino + 348 msiq_id - msiq_state_p->msiq_1st_msiq_id; 349 350 DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: " 351 "msiq_id 0x%x devino 0x%x\n", msiq_id, devino); 352 353 return (devino); 354 } 355 356 /* 357 * px_devino_to_msiqid() 358 */ 359 msiqid_t 360 px_devino_to_msiqid(px_t *px_p, devino_t devino) 361 { 362 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 363 msiqid_t msiq_id; 364 365 msiq_id = msiq_state_p->msiq_1st_msiq_id + 366 devino - msiq_state_p->msiq_1st_devino; 367 368 DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: " 369 "devino 0x%x msiq_id 0x%x\n", devino, msiq_id); 370 371 return (msiq_id); 372 } 373 374 /* 375 * px_msiq_get_props() 376 */ 377 static void 378 px_msiq_get_props(px_t *px_p) 379 { 380 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 381 int ret = DDI_SUCCESS; 382 int length = sizeof (int); 383 char *valuep = NULL; 384 385 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n"); 386 387 /* #msi-eqs */ 388 msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 389 DDI_PROP_DONTPASS, "#msi-eqs", PX_DEFAULT_MSIQ_CNT); 390 391 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_cnt=%d\n", 392 msiq_state_p->msiq_cnt); 393 394 /* msi-eq-size */ 395 msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 396 DDI_PROP_DONTPASS, "msi-eq-size", PX_DEFAULT_MSIQ_REC_CNT); 397 398 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_rec_cnt=%d\n", 399 msiq_state_p->msiq_rec_cnt); 400 401 /* msi-eq-to-devino: msi-eq#, devino# fields */ 402 ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC, 403 DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, 404 &length); 405 406 if (ret == DDI_PROP_SUCCESS) { 407 msiq_state_p->msiq_1st_msiq_id = 408 ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no; 409 msiq_state_p->msiq_1st_devino = 410 ((px_msi_eq_to_devino_t *)valuep)->devino_no; 411 kmem_free(valuep, (size_t)length); 412 } else { 413 msiq_state_p->msiq_1st_msiq_id = PX_DEFAULT_MSIQ_1ST_MSIQ_ID; 414 msiq_state_p->msiq_1st_devino = PX_DEFAULT_MSIQ_1ST_DEVINO; 415 } 416 417 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_msiq_id=%d\n", 418 msiq_state_p->msiq_1st_msiq_id); 419 420 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_devino=%d\n", 421 msiq_state_p->msiq_1st_devino); 422 } 423