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