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 /* 23 * Copyright 2008 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 #include <sys/types.h> 30 #include <sys/kmem.h> 31 #include <sys/note.h> 32 33 #include "ghd.h" 34 35 36 37 /*ARGSUSED*/ 38 gtgt_t * 39 ghd_target_init(dev_info_t *hba_dip, 40 dev_info_t *tgt_dip, 41 ccc_t *cccp, 42 size_t tgt_private_size, 43 void *hba_private, 44 ushort_t target, 45 uchar_t lun) 46 { 47 _NOTE(ARGUNUSED(hba_dip)) 48 gtgt_t *gtgtp; 49 size_t size = sizeof (*gtgtp) + tgt_private_size; 50 gdev_t *gdevp; 51 ulong_t maxactive; 52 53 gtgtp = kmem_zalloc(size, KM_SLEEP); 54 55 /* 56 * initialize the per instance structure 57 */ 58 59 gtgtp->gt_tgt_private = (void *)(gtgtp + 1); 60 gtgtp->gt_size = size; 61 gtgtp->gt_hba_private = hba_private; 62 gtgtp->gt_target = target; 63 gtgtp->gt_lun = lun; 64 gtgtp->gt_ccc = cccp; 65 66 /* 67 * set the queue's maxactive to 1 if 68 * property not specified on target or hba devinfo node 69 */ 70 maxactive = ddi_getprop(DDI_DEV_T_ANY, tgt_dip, 0, "ghd-maxactive", 1); 71 gtgtp->gt_maxactive = maxactive; 72 73 /* initialize the linked list pointers */ 74 GTGT_INIT(gtgtp); 75 76 /* 77 * grab both mutexes so the queue structures 78 * stay stable while adding this instance to the linked lists 79 */ 80 mutex_enter(&cccp->ccc_hba_mutex); 81 mutex_enter(&cccp->ccc_waitq_mutex); 82 83 /* 84 * Search the HBA's linked list of device structures. 85 * 86 * If this device is already attached then link this instance 87 * to the existing per-device-structure on the ccc_devs list. 88 * 89 */ 90 gdevp = CCCP2GDEVP(cccp); 91 while (gdevp != NULL) { 92 if (gdevp->gd_target == target && gdevp->gd_lun == lun) { 93 GDBG_WAITQ(("ghd_target_init(%d,%d) found gdevp 0x%p" 94 " gtgtp 0x%p max %lu\n", target, lun, 95 (void *)gdevp, (void *)gtgtp, maxactive)); 96 97 goto foundit; 98 } 99 gdevp = GDEV_NEXTP(gdevp); 100 } 101 102 /* 103 * Not found. This is the first instance for this device. 104 */ 105 106 107 /* allocate the per-device-structure */ 108 109 gdevp = kmem_zalloc(sizeof (*gdevp), KM_SLEEP); 110 gdevp->gd_target = target; 111 gdevp->gd_lun = lun; 112 113 /* 114 * link this second level queue to the HBA's first 115 * level queue 116 */ 117 GDEV_QATTACH(gdevp, cccp, maxactive); 118 119 GDBG_WAITQ(("ghd_target_init(%d,%d) new gdevp 0x%p gtgtp 0x%p" 120 " max %lu\n", target, lun, (void *)gdevp, (void *)gtgtp, 121 maxactive)); 122 123 foundit: 124 125 /* save the ptr to the per device structure */ 126 gtgtp->gt_gdevp = gdevp; 127 128 /* Add the per instance structure to the per device list */ 129 GTGT_ATTACH(gtgtp, gdevp); 130 131 ghd_waitq_process_and_mutex_exit(cccp); 132 133 return (gtgtp); 134 } 135 136 /*ARGSUSED*/ 137 void 138 ghd_target_free(dev_info_t *hba_dip, 139 dev_info_t *tgt_dip, 140 ccc_t *cccp, 141 gtgt_t *gtgtp) 142 { 143 _NOTE(ARGUNUSED(hba_dip,tgt_dip)) 144 145 gdev_t *gdevp = gtgtp->gt_gdevp; 146 147 GDBG_WAITQ(("ghd_target_free(%d,%d) gdevp-0x%p gtgtp 0x%p\n", 148 gtgtp->gt_target, gtgtp->gt_lun, (void *)gdevp, (void *)gtgtp)); 149 150 /* 151 * grab both mutexes so the queue structures 152 * stay stable while deleting this instance 153 */ 154 mutex_enter(&cccp->ccc_hba_mutex); 155 mutex_enter(&cccp->ccc_waitq_mutex); 156 157 ASSERT(gdevp->gd_ninstances > 0); 158 159 /* 160 * remove this per-instance structure from the device list and 161 * free the memory 162 */ 163 GTGT_DEATTACH(gtgtp, gdevp); 164 kmem_free((caddr_t)gtgtp, gtgtp->gt_size); 165 166 if (gdevp->gd_ninstances == 1) { 167 GDBG_WAITQ(("ghd_target_free: N=1 gdevp 0x%p\n", 168 (void *)gdevp)); 169 /* 170 * If there's now just one instance left attached to this 171 * device then reset the queue's max active value 172 * from that instance's saved value. 173 */ 174 gtgtp = GDEVP2GTGTP(gdevp); 175 GDEV_MAXACTIVE(gdevp) = gtgtp->gt_maxactive; 176 177 } else if (gdevp->gd_ninstances == 0) { 178 /* else no instances left */ 179 GDBG_WAITQ(("ghd_target_free: N=0 gdevp 0x%p\n", 180 (void *)gdevp)); 181 182 /* detach this per-dev-structure from the HBA's dev list */ 183 GDEV_QDETACH(gdevp, cccp); 184 kmem_free(gdevp, sizeof (*gdevp)); 185 186 } 187 #if defined(GHD_DEBUG) || defined(__lint) 188 else { 189 /* leave maxactive set to 1 */ 190 GDBG_WAITQ(("ghd_target_free: N>1 gdevp 0x%p\n", 191 (void *)gdevp)); 192 } 193 #endif 194 195 ghd_waitq_process_and_mutex_exit(cccp); 196 } 197 198 void 199 ghd_waitq_shuffle_up(ccc_t *cccp, gdev_t *gdevp) 200 { 201 gcmd_t *gcmdp; 202 203 ASSERT(mutex_owned(&cccp->ccc_waitq_mutex)); 204 205 GDBG_WAITQ(("ghd_waitq_shuffle_up: cccp 0x%p gdevp 0x%p N %ld " 206 "max %ld\n", (void *)cccp, (void *)gdevp, GDEV_NACTIVE(gdevp), 207 GDEV_MAXACTIVE(gdevp))); 208 for (;;) { 209 /* 210 * Now check the device wait queue throttle to see if I can 211 * shuffle up a request to the HBA wait queue. 212 */ 213 if (GDEV_NACTIVE(gdevp) >= GDEV_MAXACTIVE(gdevp)) { 214 GDBG_WAITQ(("ghd_waitq_shuffle_up: N>MAX gdevp 0x%p\n", 215 (void *)gdevp)); 216 return; 217 } 218 219 /* 220 * single thread requests while multiple instances 221 * because the different target drives might have 222 * conflicting maxactive throttles. 223 */ 224 if (gdevp->gd_ninstances > 1 && GDEV_NACTIVE(gdevp) > 0) { 225 GDBG_WAITQ(("ghd_waitq_shuffle_up: multi gdevp 0x%p\n", 226 (void *)gdevp)); 227 return; 228 } 229 230 /* 231 * promote the topmost request from the device queue to 232 * the HBA queue. 233 */ 234 if ((gcmdp = L2_remove_head(&GDEV_QHEAD(gdevp))) == NULL) { 235 /* the device is empty so we're done */ 236 GDBG_WAITQ(("ghd_waitq_shuffle_up: MT gdevp 0x%p\n", 237 (void *)gdevp)); 238 return; 239 } 240 L2_add(&GHBA_QHEAD(cccp), &gcmdp->cmd_q, gcmdp); 241 GDEV_NACTIVE(gdevp)++; 242 gcmdp->cmd_waitq_level++; 243 GDBG_WAITQ(("ghd_waitq_shuffle_up: gdevp 0x%p gcmdp 0x%p\n", 244 (void *)gdevp, (void *)gcmdp)); 245 } 246 } 247 248 249 void 250 ghd_waitq_delete(ccc_t *cccp, gcmd_t *gcmdp) 251 { 252 gtgt_t *gtgtp = GCMDP2GTGTP(gcmdp); 253 gdev_t *gdevp = gtgtp->gt_gdevp; 254 #if defined(GHD_DEBUG) || defined(__lint) 255 Q_t *qp = &gdevp->gd_waitq; 256 #endif 257 258 ASSERT(mutex_owned(&cccp->ccc_hba_mutex)); 259 mutex_enter(&cccp->ccc_waitq_mutex); 260 261 /* 262 * Adjust all queue counters. If this request is being aborted 263 * it might only have made it to the target queue. Otherwise, 264 * both the target and hba queue have to be adjusted when a 265 * request is completed normally. The cmd_waitq_level value 266 * indicates which queue counters need to be adjusted. It's 267 * incremented as the request progresses up the queues. 268 */ 269 switch (gcmdp->cmd_waitq_level) { 270 case 0: 271 break; 272 case 1: 273 /* 274 * If this is an early-timeout, or early-abort, the request 275 * is still linked onto a waitq. Remove it now. If it's 276 * an active request and no longer on the waitq then calling 277 * L2_delete a second time does no harm. 278 */ 279 L2_delete(&gcmdp->cmd_q); 280 break; 281 282 case 2: 283 L2_delete(&gcmdp->cmd_q); 284 #if defined(GHD_DEBUG) || defined(__lint) 285 if (GDEV_NACTIVE(gdevp) == 0) 286 debug_enter("\n\nGHD WAITQ DELETE\n\n"); 287 #endif 288 GDEV_NACTIVE(gdevp)--; 289 break; 290 291 case 3: 292 /* it's an active or completed command */ 293 #if defined(GHD_DEBUG) || defined(__lint) 294 if (GDEV_NACTIVE(gdevp) == 0 || GHBA_NACTIVE(cccp) == 0) 295 debug_enter("\n\nGHD WAITQ DELETE\n\n"); 296 #endif 297 GDEV_NACTIVE(gdevp)--; 298 GHBA_NACTIVE(cccp)--; 299 break; 300 301 default: 302 /* this shouldn't happen */ 303 #if defined(GHD_DEBUG) || defined(__lint) 304 debug_enter("\n\nGHD WAITQ LEVEL > 3\n\n"); 305 #endif 306 break; 307 } 308 309 GDBG_WAITQ(("ghd_waitq_delete: gcmdp 0x%p qp 0x%p level %ld\n", 310 (void *)gcmdp, (void *)qp, gcmdp->cmd_waitq_level)); 311 312 313 /* 314 * There's probably now more room in the HBA queue. Move 315 * up as many requests as possible. 316 */ 317 ghd_waitq_shuffle_up(cccp, gdevp); 318 319 mutex_exit(&cccp->ccc_waitq_mutex); 320 } 321 322 323 int 324 ghd_waitq_process_and_mutex_hold(ccc_t *cccp) 325 { 326 gcmd_t *gcmdp; 327 int rc = FALSE; 328 329 ASSERT(mutex_owned(&cccp->ccc_hba_mutex)); 330 ASSERT(mutex_owned(&cccp->ccc_waitq_mutex)); 331 332 for (;;) { 333 if (L2_EMPTY(&GHBA_QHEAD(cccp))) { 334 /* return if the list is empty */ 335 GDBG_WAITQ(("ghd_waitq_proc: MT cccp 0x%p qp 0x%p\n", 336 (void *)cccp, (void *)&cccp->ccc_waitq)); 337 break; 338 } 339 if (GHBA_NACTIVE(cccp) >= GHBA_MAXACTIVE(cccp)) { 340 /* return if the HBA is too active */ 341 GDBG_WAITQ(("ghd_waitq_proc: N>M cccp 0x%p qp 0x%p" 342 " N %ld max %ld\n", (void *)cccp, 343 (void *)&cccp->ccc_waitq, 344 GHBA_NACTIVE(cccp), 345 GHBA_MAXACTIVE(cccp))); 346 break; 347 } 348 349 /* 350 * bail out if the wait queue has been 351 * "held" by the HBA driver 352 */ 353 if (cccp->ccc_waitq_held) { 354 GDBG_WAITQ(("ghd_waitq_proc: held")); 355 return (rc); 356 } 357 358 if (cccp->ccc_waitq_frozen) { 359 360 clock_t lbolt, delay_in_hz, time_to_wait; 361 362 delay_in_hz = 363 drv_usectohz(cccp->ccc_waitq_freezedelay * 1000); 364 365 lbolt = ddi_get_lbolt(); 366 time_to_wait = delay_in_hz - 367 (lbolt - cccp->ccc_waitq_freezetime); 368 369 if (time_to_wait > 0) { 370 /* 371 * stay frozen; we'll be called again 372 * by ghd_timeout_softintr() 373 */ 374 GDBG_WAITQ(("ghd_waitq_proc: frozen")); 375 return (rc); 376 } else { 377 /* unfreeze and continue */ 378 GDBG_WAITQ(("ghd_waitq_proc: unfreezing")); 379 cccp->ccc_waitq_freezetime = 0; 380 cccp->ccc_waitq_freezedelay = 0; 381 cccp->ccc_waitq_frozen = 0; 382 } 383 } 384 385 gcmdp = (gcmd_t *)L2_remove_head(&GHBA_QHEAD(cccp)); 386 GHBA_NACTIVE(cccp)++; 387 gcmdp->cmd_waitq_level++; 388 mutex_exit(&cccp->ccc_waitq_mutex); 389 390 /* 391 * Start up the next I/O request 392 */ 393 ASSERT(gcmdp != NULL); 394 gcmdp->cmd_state = GCMD_STATE_ACTIVE; 395 if (!(*cccp->ccc_hba_start)(cccp->ccc_hba_handle, gcmdp)) { 396 /* if the HBA rejected the request, requeue it */ 397 gcmdp->cmd_state = GCMD_STATE_WAITQ; 398 mutex_enter(&cccp->ccc_waitq_mutex); 399 GHBA_NACTIVE(cccp)--; 400 gcmdp->cmd_waitq_level--; 401 L2_add_head(&GHBA_QHEAD(cccp), &gcmdp->cmd_q, gcmdp); 402 GDBG_WAITQ(("ghd_waitq_proc: busy cccp 0x%p gcmdp 0x%p" 403 " handle 0x%p\n", (void *)cccp, (void *)gcmdp, 404 cccp->ccc_hba_handle)); 405 break; 406 } 407 rc = TRUE; 408 mutex_enter(&cccp->ccc_waitq_mutex); 409 GDBG_WAITQ(("ghd_waitq_proc: ++ cccp 0x%p gcmdp 0x%p N %ld\n", 410 (void *)cccp, (void *)gcmdp, GHBA_NACTIVE(cccp))); 411 } 412 ASSERT(mutex_owned(&cccp->ccc_hba_mutex)); 413 ASSERT(mutex_owned(&cccp->ccc_waitq_mutex)); 414 return (rc); 415 } 416 417 void 418 ghd_waitq_process_and_mutex_exit(ccc_t *cccp) 419 { 420 ASSERT(mutex_owned(&cccp->ccc_hba_mutex)); 421 ASSERT(mutex_owned(&cccp->ccc_waitq_mutex)); 422 423 GDBG_WAITQ(("ghd_waitq_process_and_mutex_exit: cccp 0x%p\n", 424 (void *)cccp)); 425 426 (void) ghd_waitq_process_and_mutex_hold(cccp); 427 428 /* 429 * Release the mutexes in the opposite order that they 430 * were acquired to prevent requests queued by 431 * ghd_transport() from getting hung up in the wait queue. 432 */ 433 mutex_exit(&cccp->ccc_hba_mutex); 434 mutex_exit(&cccp->ccc_waitq_mutex); 435 } 436