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 2008 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/modctl.h> 36 #include <sys/disp.h> 37 #include <sys/stat.h> 38 #include <sys/ddi_impldefs.h> 39 #include "px_obj.h" 40 41 static void px_msiq_get_props(px_t *px_p); 42 43 /* 44 * px_msiq_attach() 45 */ 46 int 47 px_msiq_attach(px_t *px_p) 48 { 49 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 50 int i, ret = DDI_SUCCESS; 51 52 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_attach\n"); 53 54 /* 55 * Check for all MSIQ related properties and 56 * save all information. 57 * 58 * Avaialble MSIQs and its properties. 59 */ 60 px_msiq_get_props(px_p); 61 62 /* 63 * 10% of available MSIQs are reserved for the PCIe messages. 64 * Around 90% of available MSIQs are reserved for the MSI/Xs. 65 */ 66 msiq_state_p->msiq_msg_qcnt = howmany(msiq_state_p->msiq_cnt, 10); 67 msiq_state_p->msiq_msi_qcnt = msiq_state_p->msiq_cnt - 68 msiq_state_p->msiq_msg_qcnt; 69 70 msiq_state_p->msiq_1st_msi_qid = msiq_state_p->msiq_1st_msiq_id; 71 msiq_state_p->msiq_next_msi_qid = msiq_state_p->msiq_1st_msi_qid; 72 73 msiq_state_p->msiq_1st_msg_qid = msiq_state_p->msiq_1st_msiq_id + 74 msiq_state_p->msiq_msi_qcnt; 75 msiq_state_p->msiq_next_msg_qid = msiq_state_p->msiq_1st_msg_qid; 76 77 mutex_init(&msiq_state_p->msiq_mutex, NULL, MUTEX_DRIVER, NULL); 78 msiq_state_p->msiq_p = kmem_zalloc(msiq_state_p->msiq_cnt * 79 sizeof (px_msiq_t), KM_SLEEP); 80 81 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 82 msiq_state_p->msiq_p[i].msiq_id = 83 msiq_state_p->msiq_1st_msiq_id + i; 84 msiq_state_p->msiq_p[i].msiq_refcnt = 0; 85 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_FREE; 86 } 87 88 if ((ret = px_lib_msiq_init(px_p->px_dip)) != DDI_SUCCESS) 89 px_msiq_detach(px_p); 90 91 return (ret); 92 } 93 94 /* 95 * px_msiq_detach() 96 */ 97 void 98 px_msiq_detach(px_t *px_p) 99 { 100 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 101 102 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_detach\n"); 103 104 if (px_lib_msiq_fini(px_p->px_dip) != DDI_SUCCESS) { 105 DBG(DBG_MSIQ, px_p->px_dip, 106 "px_lib_msiq_fini: failed\n"); 107 } 108 109 mutex_destroy(&msiq_state_p->msiq_mutex); 110 kmem_free(msiq_state_p->msiq_p, 111 msiq_state_p->msiq_cnt * sizeof (px_msiq_t)); 112 113 bzero(&px_p->px_ib_p->ib_msiq_state, sizeof (px_msiq_state_t)); 114 } 115 116 /* 117 * px_msiq_detach() 118 */ 119 void 120 px_msiq_resume(px_t *px_p) 121 { 122 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 123 int i; 124 125 for (i = 0; i < msiq_state_p->msiq_cnt; i++) { 126 (void) px_lib_msiq_gethead(px_p->px_dip, i, 127 &msiq_state_p->msiq_p[i].msiq_curr_head_index); 128 msiq_state_p->msiq_p[i].msiq_new_head_index = 0; 129 msiq_state_p->msiq_p[i].msiq_recs2process = 0; 130 } 131 } 132 133 /* 134 * px_msiq_alloc() 135 */ 136 int 137 px_msiq_alloc(px_t *px_p, msiq_rec_type_t rec_type, msiqid_t *msiq_id_p) 138 { 139 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 140 msiqid_t first_msiq_id, *next_msiq_index; 141 uint_t msiq_cnt; 142 int i; 143 144 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_alloc\n"); 145 146 mutex_enter(&msiq_state_p->msiq_mutex); 147 148 if (rec_type == MSG_REC) { 149 msiq_cnt = msiq_state_p->msiq_msg_qcnt; 150 first_msiq_id = msiq_state_p->msiq_1st_msg_qid; 151 next_msiq_index = &msiq_state_p->msiq_next_msg_qid; 152 } else { 153 msiq_cnt = msiq_state_p->msiq_msi_qcnt; 154 first_msiq_id = msiq_state_p->msiq_1st_msi_qid; 155 next_msiq_index = &msiq_state_p->msiq_next_msi_qid; 156 } 157 158 /* Allocate MSIQs */ 159 for (i = first_msiq_id; i < (first_msiq_id + msiq_cnt); i++) { 160 if (msiq_state_p->msiq_p[i].msiq_state == MSIQ_STATE_FREE) { 161 msiq_state_p->msiq_p[i].msiq_state = MSIQ_STATE_INUSE; 162 msiq_state_p->msiq_p[i].msiq_refcnt = 1; 163 (void) px_lib_msiq_gethead(px_p->px_dip, i, 164 &msiq_state_p->msiq_p[i].msiq_curr_head_index); 165 break; 166 } 167 } 168 169 /* 170 * There are no free MSIQ. 171 * Use next available MSIQ. 172 */ 173 if (i >= (first_msiq_id + msiq_cnt)) { 174 i = *next_msiq_index; 175 msiq_state_p->msiq_p[i].msiq_refcnt++; 176 } 177 178 *msiq_id_p = msiq_state_p->msiq_p[i].msiq_id; 179 DBG(DBG_MSIQ, px_p->px_dip, 180 "px_msiq_alloc: msiq_id 0x%x\n", *msiq_id_p); 181 182 (*next_msiq_index)++; 183 184 if (*next_msiq_index >= (first_msiq_id + msiq_cnt)) 185 *next_msiq_index = first_msiq_id; 186 187 mutex_exit(&msiq_state_p->msiq_mutex); 188 return (DDI_SUCCESS); 189 } 190 191 /* 192 * px_msiq_free() 193 */ 194 int 195 px_msiq_free(px_t *px_p, msiqid_t msiq_id) 196 { 197 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 198 199 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_free: msiq_id 0x%x", msiq_id); 200 201 mutex_enter(&msiq_state_p->msiq_mutex); 202 203 if ((msiq_id < msiq_state_p->msiq_1st_msiq_id) || (msiq_id >= 204 (msiq_state_p->msiq_1st_msiq_id + msiq_state_p->msiq_cnt))) { 205 DBG(DBG_MSIQ, px_p->px_dip, 206 "px_msiq_free: Invalid msiq_id 0x%x", msiq_id); 207 return (DDI_FAILURE); 208 } 209 210 if (--msiq_state_p->msiq_p[msiq_id].msiq_refcnt == 0) 211 msiq_state_p->msiq_p[msiq_id].msiq_state = MSIQ_STATE_FREE; 212 213 mutex_exit(&msiq_state_p->msiq_mutex); 214 return (DDI_SUCCESS); 215 } 216 217 /* 218 * px_msiqid_to_devino() 219 */ 220 devino_t 221 px_msiqid_to_devino(px_t *px_p, msiqid_t msiq_id) 222 { 223 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 224 devino_t devino; 225 226 devino = msiq_state_p->msiq_1st_devino + 227 msiq_id - msiq_state_p->msiq_1st_msiq_id; 228 229 DBG(DBG_MSIQ, px_p->px_dip, "px_msiqid_to_devino: " 230 "msiq_id 0x%x devino 0x%x\n", msiq_id, devino); 231 232 return (devino); 233 } 234 235 /* 236 * px_devino_to_msiqid() 237 */ 238 msiqid_t 239 px_devino_to_msiqid(px_t *px_p, devino_t devino) 240 { 241 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 242 msiqid_t msiq_id; 243 244 msiq_id = msiq_state_p->msiq_1st_msiq_id + 245 devino - msiq_state_p->msiq_1st_devino; 246 247 DBG(DBG_MSIQ, px_p->px_dip, "px_devino_to_msiq: " 248 "devino 0x%x msiq_id 0x%x\n", devino, msiq_id); 249 250 return (msiq_id); 251 } 252 253 /* 254 * px_msiq_get_props() 255 */ 256 static void 257 px_msiq_get_props(px_t *px_p) 258 { 259 px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 260 int ret = DDI_SUCCESS; 261 int length = sizeof (int); 262 char *valuep = NULL; 263 264 DBG(DBG_MSIQ, px_p->px_dip, "px_msiq_get_props\n"); 265 266 /* #msi-eqs */ 267 msiq_state_p->msiq_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 268 DDI_PROP_DONTPASS, "#msi-eqs", PX_DEFAULT_MSIQ_CNT); 269 270 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_cnt=%d\n", 271 msiq_state_p->msiq_cnt); 272 273 /* msi-eq-size */ 274 msiq_state_p->msiq_rec_cnt = ddi_getprop(DDI_DEV_T_ANY, px_p->px_dip, 275 DDI_PROP_DONTPASS, "msi-eq-size", PX_DEFAULT_MSIQ_REC_CNT); 276 277 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_rec_cnt=%d\n", 278 msiq_state_p->msiq_rec_cnt); 279 280 /* msi-eq-to-devino: msi-eq#, devino# fields */ 281 ret = ddi_prop_op(DDI_DEV_T_ANY, px_p->px_dip, PROP_LEN_AND_VAL_ALLOC, 282 DDI_PROP_DONTPASS, "msi-eq-to-devino", (caddr_t)&valuep, 283 &length); 284 285 if (ret == DDI_PROP_SUCCESS) { 286 msiq_state_p->msiq_1st_msiq_id = 287 ((px_msi_eq_to_devino_t *)valuep)->msi_eq_no; 288 msiq_state_p->msiq_1st_devino = 289 ((px_msi_eq_to_devino_t *)valuep)->devino_no; 290 kmem_free(valuep, (size_t)length); 291 } else { 292 msiq_state_p->msiq_1st_msiq_id = PX_DEFAULT_MSIQ_1ST_MSIQ_ID; 293 msiq_state_p->msiq_1st_devino = PX_DEFAULT_MSIQ_1ST_DEVINO; 294 } 295 296 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_msiq_id=%d\n", 297 msiq_state_p->msiq_1st_msiq_id); 298 299 DBG(DBG_MSIQ, px_p->px_dip, "obp: msiq_1st_devino=%d\n", 300 msiq_state_p->msiq_1st_devino); 301 } 302