1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 14 */ 15 16 #include <sys/sdt.h> 17 #include "cpqary3.h" 18 19 /* 20 * Local Functions Definitions 21 */ 22 23 uint8_t cpqary3_format_unit(cpqary3_cmdpvt_t *); 24 25 static uint8_t cpqary3_probe4LVs(cpqary3_t *); 26 static uint8_t cpqary3_probe4Tapes(cpqary3_t *); 27 28 29 /* 30 * Function : cpqary3_probe4targets 31 * Description : This routine detects all existing logical drives 32 * and updates per target structure. 33 * Called By : cpqary3_tgt_init() 34 * Parameters : per-controller 35 * Calls : cpqary3_probe4LVs(), cpqary3_probe4Tapes() 36 * Return Values: SUCCESS/ FAILURE 37 * [Shall fail only if Memory Constraints exist, the 38 * controller is defective/does not respond] 39 */ 40 uint8_t 41 cpqary3_probe4targets(cpqary3_t *cpqary3p) 42 { 43 uint8_t rv; 44 45 rv = cpqary3_probe4LVs(cpqary3p); 46 47 if (CPQARY3_FAILURE == rv) { 48 return (rv); 49 } 50 51 rv = cpqary3_probe4Tapes(cpqary3p); 52 53 if (CPQARY3_FAILURE == rv) { 54 return (rv); 55 } 56 57 return (CPQARY3_SUCCESS); 58 59 } 60 61 /* 62 * Function : cpqary3_build_cmdlist 63 * Description : This routine builds the command list for the specific 64 * opcode. 65 * Called By : cpqary3_transport() 66 * Parameters : cmdlist pvt struct, target id as received by SA. 67 * Calls : None 68 * Return Values: SUCCESS : Build is successful 69 * FAILURE : Build has Failed 70 */ 71 uint8_t 72 cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid) 73 { 74 int cntr; 75 cpqary3_t *cpqary3p; 76 struct buf *bfp; 77 cpqary3_tgt_t *tgtp; 78 CommandList_t *cmdlistp; 79 80 RETURN_FAILURE_IF_NULL(cpqary3_cmdpvtp); 81 82 if (NULL == (cpqary3p = cpqary3_cmdpvtp->ctlr)) 83 return (CPQARY3_FAILURE); 84 85 bfp = (struct buf *)cpqary3_cmdpvtp->pvt_pkt->bf; 86 87 tgtp = cpqary3p->cpqary3_tgtp[tid]; 88 89 if (!tgtp) { 90 return (CPQARY3_FAILURE); 91 } 92 93 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 94 95 /* Update Cmd Header */ 96 cmdlistp->Header.SGList = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; 97 cmdlistp->Header.SGTotal = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; 98 cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_OSCMD_SUCCESS; 99 100 if (tgtp->type == CPQARY3_TARGET_CTLR) { 101 cmdlistp->Header.LUN.PhysDev.TargetId = 0; 102 cmdlistp->Header.LUN.PhysDev.Bus = 0; 103 cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR; 104 } else if (tgtp->type == CPQARY3_TARGET_LOG_VOL) { 105 cmdlistp->Header.LUN.LogDev.VolId = tgtp->logical_id; 106 cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR; 107 } else if (tgtp->type == CPQARY3_TARGET_TAPE) { 108 bcopy(&(tgtp->PhysID), &(cmdlistp->Header.LUN.PhysDev), 109 sizeof (PhysDevAddr_t)); 110 111 DTRACE_PROBE1(build_cmdlist_tape, CommandList_t *, cmdlistp); 112 } 113 114 /* Cmd Request */ 115 cmdlistp->Request.CDBLen = cpqary3_cmdpvtp->pvt_pkt->cdb_len; 116 117 bcopy((caddr_t)cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_cdbp, 118 (caddr_t)cmdlistp->Request.CDB, cpqary3_cmdpvtp->pvt_pkt->cdb_len); 119 120 121 cmdlistp->Request.Type.Type = CISS_TYPE_CMD; 122 cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED; 123 124 DTRACE_PROBE2(build_cmdlist_buf, struct buf *, bfp, 125 CommandList_t *, cmdlistp); 126 127 if (bfp && (bfp->b_flags & B_READ)) 128 cmdlistp->Request.Type.Direction = CISS_XFER_READ; 129 else if (bfp && (bfp->b_flags & B_WRITE)) 130 cmdlistp->Request.Type.Direction = CISS_XFER_WRITE; 131 else 132 cmdlistp->Request.Type.Direction = CISS_XFER_NONE; 133 /* 134 * Looks like the above Direction is going for a toss in case of 135 * MSA20(perticularly for 0x0a-write) connected to SMART Array. 136 * If the above check fails, the below switch should take care. 137 */ 138 139 switch (cmdlistp->Request.CDB[0]) { 140 case 0x08: 141 case 0x28: 142 cmdlistp->Request.Type.Direction = CISS_XFER_READ; 143 break; 144 case 0x0A: 145 case 0x2A: 146 cmdlistp->Request.Type.Direction = CISS_XFER_WRITE; 147 break; 148 } 149 /* 150 * NEED to increase this TimeOut value when the concerned 151 * targets are tape devices(i.e., we need to do it here manually). 152 */ 153 cmdlistp->Request.Timeout = 2 * 154 (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_time); 155 156 for (cntr = 0; cntr < cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; cntr++) { 157 cmdlistp->SG[cntr].Addr = 158 cpqary3_cmdpvtp->pvt_pkt-> 159 cmd_dmacookies[cntr].dmac_laddress; 160 cmdlistp->SG[cntr].Len = (uint32_t) 161 cpqary3_cmdpvtp->pvt_pkt->cmd_dmacookies[cntr].dmac_size; 162 } 163 164 return (CPQARY3_SUCCESS); 165 } 166 167 168 /* 169 * Function : cpqary3_send_abortcmd 170 * Description : Sends the Abort command to abort 171 * a set of cmds(on a target) or a cmdlist. 172 * Called By : cpqary3_abort 173 * Parameters : per controller, target_id, cmdlist to abort 174 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send(), 175 * cpqary3_synccmd_free() 176 * Return Values: SUCCESS - abort cmd submit is successful. 177 * FAILURE - Could not submit the abort cmd. 178 */ 179 uint8_t 180 cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id, 181 CommandList_t *cmdlist2abortp) 182 { 183 CommandList_t *cmdlistp; 184 cpqary3_tgt_t *cpqtgtp; 185 cpqary3_tag_t *cpqary3_tagp; 186 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 187 188 /* 189 * NOTE : DO NOT perform this operation for cmdlist2abortp. 190 * It may be NULL 191 */ 192 RETURN_FAILURE_IF_NULL(cpqary3p); 193 194 if (target_id == CTLR_SCSI_ID) 195 return (CPQARY3_FAILURE); 196 197 cpqtgtp = cpqary3p->cpqary3_tgtp[target_id]; 198 199 if (!cpqtgtp) { 200 return (CPQARY3_FAILURE); 201 } 202 203 /* 204 * Occupy the Command List 205 * Update the Command List accordingly 206 * Submit the command and wait for a signal 207 */ 208 209 /* BGB: CVFIX -> Introduced the call to cpqary3_synccmd_alloc */ 210 cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, 0); 211 if (cpqary3_cmdpvtp == NULL) 212 return (CPQARY3_FAILURE); 213 214 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 215 216 cmdlistp->Header.SGList = 0; 217 cmdlistp->Header.SGTotal = 0; 218 cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS; 219 cmdlistp->Header.LUN.PhysDev.TargetId = 0; 220 cmdlistp->Header.LUN.PhysDev.Bus = 0; 221 cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR; 222 223 cmdlistp->Request.Type.Type = CISS_TYPE_MSG; 224 cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE; 225 cmdlistp->Request.Type.Direction = CISS_XFER_NONE; 226 cmdlistp->Request.Timeout = CISS_NO_TIMEOUT; 227 cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16; 228 cmdlistp->Request.CDB[0] = CISS_MSG_ABORT; 229 230 if (cmdlist2abortp) { /* Abort this Particular Task */ 231 cmdlistp->Request.CDB[1] = CISS_ABORT_TASK; 232 cpqary3_tagp = (cpqary3_tag_t *)&cmdlistp->Request.CDB[4]; 233 cpqary3_tagp->drvinfo_n_err = 234 cmdlist2abortp->Header.Tag.drvinfo_n_err; 235 cpqary3_tagp->tag_value = cmdlist2abortp->Header.Tag.tag_value; 236 } else { /* Abort all tasks for this Target */ 237 cmdlistp->Request.CDB[1] = CISS_ABORT_TASKSET; 238 239 switch (cpqtgtp->type) { 240 case CPQARY3_TARGET_LOG_VOL: 241 cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR; 242 cmdlistp->Header.LUN.LogDev.VolId = cpqtgtp->logical_id; 243 break; 244 case CPQARY3_TARGET_TAPE: 245 bcopy(&(cpqtgtp->PhysID), 246 &(cmdlistp->Header.LUN.PhysDev), 247 sizeof (PhysDevAddr_t)); 248 } 249 } 250 251 /* PERF */ 252 253 cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 254 255 /* PERF */ 256 257 /* BGB: CVFIX -> Introduced a call to cpqary3_synccmd_send */ 258 if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 30000, 259 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 260 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 261 return (CPQARY3_FAILURE); 262 } 263 264 if (cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err == 265 CPQARY3_SYNCCMD_FAILURE) { 266 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 267 return (CPQARY3_FAILURE); 268 } 269 270 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 271 272 return (CPQARY3_SUCCESS); 273 274 } 275 276 277 /* 278 * Function : cpqary3_fulsh_cache 279 * Description : This routine flushes the controller cache. 280 * Called By : cpqary3_detach(), cpqary3_additional_cmd() 281 * Parameters : per controller 282 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send() 283 * cpqary3_synccmd_free() 284 * Return Values: None 285 */ 286 void 287 cpqary3_flush_cache(cpqary3_t *cpqary3p) 288 { 289 CommandList_t *cmdlistp; 290 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 291 292 /* 293 * Occupy the Command List 294 * Allocate Physically Contigous Memory for the FLUSH CACHE buffer 295 * Update the Command List accordingly 296 * Submit the command and wait for a signal 297 */ 298 299 ASSERT(cpqary3p != NULL); 300 301 /* grab a command and allocate a dma buffer */ 302 cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, 303 sizeof (flushcache_buf_t)); 304 if (cpqary3_cmdpvtp == NULL) 305 return; 306 307 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 308 cmdlistp->Header.SGList = 1; 309 cmdlistp->Header.SGTotal = 1; 310 cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS; 311 cmdlistp->Header.LUN.PhysDev.TargetId = 0; 312 cmdlistp->Header.LUN.PhysDev.Bus = 0; 313 cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR; 314 315 cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16; 316 cmdlistp->Request.Type.Type = CISS_TYPE_CMD; 317 cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE; 318 cmdlistp->Request.Type.Direction = CISS_XFER_WRITE; 319 cmdlistp->Request.Timeout = CISS_NO_TIMEOUT; 320 cmdlistp->Request.CDB[0] = ARRAY_WRITE; 321 cmdlistp->Request.CDB[6] = CISS_FLUSH_CACHE; /* 0xC2 */ 322 cmdlistp->Request.CDB[8] = 0x02; 323 324 /* PERF */ 325 326 cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 327 328 /* PERF */ 329 330 if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000, 331 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 332 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 333 cmn_err(CE_WARN, "CPQary3 %s : Flush Cache Operation" 334 "Failed, Timeout", cpqary3p->hba_name); 335 return; 336 } 337 338 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 339 } 340 341 /* 342 * Function : cpqary3_probe4LVs 343 * Description : This routine probes for the logical drives 344 * configured on the HP Smart Array controllers 345 * Called By : cpqary3_probe4targets() 346 * Parameters : per controller 347 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send() 348 * cpqary3_synccmd_free() 349 * Return Values: None 350 */ 351 uint8_t 352 cpqary3_probe4LVs(cpqary3_t *cpqary3p) 353 { 354 ulong_t log_lun_no = 0; 355 ulong_t lun_id = 0; 356 ulong_t ld_count = 0; 357 ulong_t i = 0; 358 ulong_t cntr = 0; 359 uint32_t data_addr_len; 360 rll_data_t *rllp; 361 CommandList_t *cmdlistp; 362 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 363 364 /* 365 * Occupy the Command List 366 * Allocate Physically Contigous Memory 367 * Update the Command List for Report Logical LUNS (rll) Command 368 * This command detects all existing logical drives. 369 * Submit and Poll for completion 370 */ 371 372 RETURN_FAILURE_IF_NULL(cpqary3p); 373 374 /* Sync Changes */ 375 cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rll_data_t)); 376 if (cpqary3_cmdpvtp == NULL) 377 return (CPQARY3_FAILURE); 378 379 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 380 rllp = (rll_data_t *)cpqary3_cmdpvtp->driverdata->sg; 381 382 cmdlistp->Header.SGList = 1; 383 cmdlistp->Header.SGTotal = 1; 384 cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS; 385 cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR; 386 387 cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12; 388 cmdlistp->Request.Timeout = CISS_NO_TIMEOUT; 389 cmdlistp->Request.Type.Type = CISS_TYPE_CMD; 390 cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED; 391 cmdlistp->Request.Type.Direction = CISS_XFER_READ; 392 cmdlistp->Request.CDB[0] = CISS_OPCODE_RLL; 393 394 data_addr_len = sizeof (rll_data_t); 395 396 cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff; 397 cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff; 398 cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff; 399 cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff; 400 401 DTRACE_PROBE2(rll_cmd_send, CommandList_t *, cmdlistp, 402 cpqary3_cmdpvt_t *, cpqary3_cmdpvtp); 403 404 /* PERF */ 405 cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 406 /* PERF */ 407 408 if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000, 409 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 410 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 411 return (CPQARY3_FAILURE); 412 } 413 414 if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err == 415 CPQARY3_SYNCCMD_FAILURE) && 416 (cpqary3_cmdpvtp->errorinfop->CommandStatus != 417 CISS_CMD_DATA_UNDERRUN)) { 418 cmn_err(CE_WARN, "CPQary3 : Probe for logical targets " 419 "returned ERROR !"); 420 DTRACE_PROBE1(rll_cmd_fail, 421 ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop); 422 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 423 return (CPQARY3_FAILURE); 424 } 425 /* Sync Changes */ 426 427 log_lun_no = ((rllp->lunlist_byte0 + (rllp->lunlist_byte1 << 8) + 428 (rllp->lunlist_byte2 << 16) + (rllp->lunlist_byte3 << 24)) / 8); 429 430 DTRACE_PROBE2(rll_cmd_result, rll_data_t *, rllp, ulong_t, log_lun_no); 431 432 /* 433 * The following is to restrict the maximum number of supported logical 434 * volumes to 32. This is very important as controller support upto 128 435 * logical volumes and this driver implementation supports only 32. 436 */ 437 438 if (log_lun_no > MAX_LOGDRV) { 439 log_lun_no = MAX_LOGDRV; 440 } 441 442 cpqary3p->num_of_targets = log_lun_no; 443 DTRACE_PROBE1(update_lvlun_count, ulong_t, log_lun_no); 444 445 /* 446 * Update per target structure with relevant information 447 * CPQARY#_TGT_ALLIGNMENT is 1 because of the following mapping: 448 * Target IDs 0-6 in the OS = Logical Drives 0 - 6 in the HBA 449 * Target ID 7 in the OS = none in the HBA 450 * Target IDs 8-32 in the OS = Logical Drives 7 - 31 in the HBA 451 * Everytime we reference a logical drive with ID > 6, we shall use 452 * the alignment. 453 */ 454 455 456 /* 457 * Depending upon the value of the variable legacy_mapping set in 458 * cpqary3_attach(), 459 * the target mapping algorithm to be used by the driver is decided. 460 * 461 * If the value of legacy_mapping is set to one, in the case of 462 * Logical Drives with holes, 463 * Targets will be renumbered by the driver as shown below 464 * Below example makes the mapping logic clear. 465 * 466 * Logical Drive 0 in the HBA -> Target ID 0 i.e., cXt0dXsx 467 * Logical Drive 2 in the HBA -> Target ID 1 i.e., cXt1dXsX 468 * Logical Drive 3 in the HBA -> Target ID 2 i.e., cXt2dXsX 469 * 470 * If the value of legacy_mapping is not one, then the Logical 471 * Drive numbers will 472 * not be renumbered in the case of holes, and the mapping 473 * will be done as shown below 474 * This will be the default mapping from 1.80 cpqary3 driver. 475 * 476 * Logical Drive 0 in the HBA -> Target ID 0 i.e. cXt0dXsx 477 * Logical Drive 2 in the HBA -> Target ID 2 i.e. cXt2dXsX 478 * Logical Drive 3 in the HBA -> Target ID 3 i.e. cXt3dXsX 479 */ 480 481 482 if (cpqary3p->legacy_mapping == 1) { 483 for (cntr = 0; cntr < log_lun_no; cntr++) { 484 i = ((cntr < CTLR_SCSI_ID) ? 485 cntr : cntr + CPQARY3_TGT_ALIGNMENT); 486 if (!(cpqary3p->cpqary3_tgtp[i] = (cpqary3_tgt_t *) 487 MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) { 488 cmn_err(CE_WARN, "CPQary3 : Failed to Detect " 489 "targets, Memory Allocation Failure"); 490 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 491 return (CPQARY3_FAILURE); 492 } 493 494 cpqary3p->cpqary3_tgtp[i]->logical_id = 495 rllp->ll_data[cntr].logical_id; 496 497 cpqary3p->cpqary3_tgtp[i]->type = 498 CPQARY3_TARGET_LOG_VOL; 499 500 DTRACE_PROBE2(lvlun_remapped, 501 cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[i], 502 rpl_data_t *, &rllp->ll_data[cntr]); 503 } 504 } else { 505 /* 506 * Fix for QXCR1000446657: Logical drives are re numbered after 507 * deleting a Logical drive. 508 * We are using new indexing mechanism to fill the 509 * cpqary3_tgtp[], 510 * Check given during memory allocation of cpqary3_tgtp 511 * elements, so that memory is not re-allocated each time the 512 * cpqary3_probe4LVs() is called. 513 * Check given while freeing the memory of the cpqary3_tgtp[] 514 * elements, when a hole is found in the Logical Drives 515 * configured. 516 */ 517 518 /* ensure that the loop will break for cntr = 32 in any case */ 519 for (cntr = 0; ((ld_count < log_lun_no) && (cntr < MAX_LOGDRV)); 520 cntr++) { 521 i = ((cntr < CTLR_SCSI_ID) ? 522 cntr : cntr + CPQARY3_TGT_ALIGNMENT); 523 lun_id = (rllp->ll_data[ld_count].logical_id & 0xFFFF); 524 if (cntr != lun_id) { 525 if (cpqary3p->cpqary3_tgtp[i]) { 526 MEM_SFREE(cpqary3p->cpqary3_tgtp[i], 527 sizeof (cpqary3_tgt_t)); 528 cpqary3p->cpqary3_tgtp[i] = NULL; 529 } 530 } else { 531 if (cpqary3p->cpqary3_tgtp[i] == NULL && 532 !(cpqary3p->cpqary3_tgtp[i] = 533 (cpqary3_tgt_t *)MEM_ZALLOC( 534 sizeof (cpqary3_tgt_t)))) { 535 cmn_err(CE_WARN, 536 "CPQary3 : Failed to Detect " 537 "targets, Memory Allocation " 538 "Failure"); 539 /* Sync Changes */ 540 cpqary3_synccmd_free(cpqary3p, 541 cpqary3_cmdpvtp); 542 /* Sync Changes */ 543 return (CPQARY3_FAILURE); 544 } 545 cpqary3p->cpqary3_tgtp[i]->logical_id = 546 rllp->ll_data[ld_count].logical_id; 547 cpqary3p->cpqary3_tgtp[i]->type = 548 CPQARY3_TARGET_LOG_VOL; 549 550 /* 551 * Send "BMIC sense logical drive status 552 * command to set the target type to 553 * CPQARY3_TARGET_NONE in case of logical 554 * drive failure 555 */ 556 557 ld_count++; 558 } 559 } 560 561 } 562 563 /* HPQacucli Changes */ 564 for (; cntr < MAX_LOGDRV; cntr++) { 565 cpqary3_tgt_t *t; 566 i = ((cntr < CTLR_SCSI_ID) ? 567 cntr : cntr + CPQARY3_TGT_ALIGNMENT); 568 t = cpqary3p->cpqary3_tgtp[i]; 569 cpqary3p->cpqary3_tgtp[i] = NULL; 570 if (t) { 571 MEM_SFREE(t, sizeof (*t)); 572 } 573 } 574 /* HPQacucli Changes */ 575 576 /* Sync Changes */ 577 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 578 /* Sync Changes */ 579 580 return (CPQARY3_SUCCESS); 581 } 582 583 /* 584 * Function : cpqary3_probe4Tapes 585 * Description : This routine probes for the logical drives 586 * configured on the HP Smart Array controllers 587 * Called By : cpqary3_probe4targets() 588 * Parameters : per controller 589 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send() 590 * cpqary3_synccmd_free() 591 * Return Values: None 592 */ 593 uint8_t 594 cpqary3_probe4Tapes(cpqary3_t *cpqary3p) 595 { 596 uint8_t phy_lun_no; 597 uint32_t ii = 0; 598 uint8_t cntr = 0; 599 uint32_t data_addr_len; 600 rpl_data_t *rplp; 601 CommandList_t *cmdlistp; 602 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 603 604 /* 605 * Occupy the Command List 606 * Allocate Physically Contigous Memory 607 * Update the Command List for Report Logical LUNS (rll) Command 608 * This command detects all existing logical drives. 609 * Submit and Poll for completion 610 */ 611 612 RETURN_FAILURE_IF_NULL(cpqary3p); 613 614 /* Sync Changes */ 615 cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rpl_data_t)); 616 if (cpqary3_cmdpvtp == NULL) 617 return (CPQARY3_FAILURE); 618 619 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 620 rplp = (rpl_data_t *)cpqary3_cmdpvtp->driverdata->sg; 621 622 /* Sync Changes */ 623 624 cmdlistp->Header.SGList = 1; 625 cmdlistp->Header.SGTotal = 1; 626 cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS; 627 cmdlistp->Header.LUN.PhysDev.TargetId = 0; 628 cmdlistp->Header.LUN.PhysDev.Bus = 0; 629 cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR; 630 631 cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12; 632 cmdlistp->Request.Timeout = CISS_NO_TIMEOUT; 633 cmdlistp->Request.Type.Type = CISS_TYPE_CMD; 634 cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED; 635 cmdlistp->Request.Type.Direction = CISS_XFER_READ; 636 cmdlistp->Request.CDB[0] = CISS_OPCODE_RPL; 637 638 data_addr_len = sizeof (rpl_data_t); 639 640 cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff; 641 cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff; 642 cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff; 643 cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff; 644 645 DTRACE_PROBE2(tape_probe_cmd_send, 646 CommandList_t *, cmdlistp, cpqary3_cmdpvt_t *, cpqary3_cmdpvtp); 647 648 /* PERF */ 649 cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 650 /* PERF */ 651 652 /* Sync Changes */ 653 654 if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000, 655 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 656 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 657 return (CPQARY3_FAILURE); 658 } 659 660 if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err == 661 CPQARY3_SYNCCMD_FAILURE) && 662 (cpqary3_cmdpvtp->errorinfop->CommandStatus != 663 CISS_CMD_DATA_UNDERRUN)) { 664 cmn_err(CE_WARN, "CPQary3 : Probe for physical targets " 665 "returned ERROR !"); 666 DTRACE_PROBE1(tape_probe_cmdfail, 667 ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop); 668 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 669 return (CPQARY3_FAILURE); 670 } 671 /* Sync Changes */ 672 673 phy_lun_no = ((rplp->lunlist_byte0 + 674 (rplp->lunlist_byte1 << 8) + 675 (rplp->lunlist_byte2 << 16) + 676 (rplp->lunlist_byte3 << 24)) / 8); 677 678 /* 679 * Update per target structure with relevant information 680 * CPQARY3_TAPE_BASE is 33 because of the following mapping: 681 * Target IDs 0-6 in the OS = Logical Drives 0 - 6 in the HBA 682 * Target ID 7 in the OS = none in the HBA 683 * Target IDs 8-32 in the OS = Logical Drives 7 - 31 in the HBA 684 * Target IDs 33 and above are reserved for Tapes and hence we need 685 * the alignment. 686 */ 687 688 689 /* 690 * HP Smart Array SAS controllers with Firmware revsion 5.14 or 691 * later support 692 * 64 Logical drives. So we are checking 693 * if the controller is SAS or CISS and then assigning the value of the 694 * TAPE BASE accordingly 695 */ 696 697 if (cpqary3p->bddef->bd_flags & SA_BD_SAS) { 698 ii = 0x41; /* MAX_LOGDRV + 1 - 64 + 1 */ 699 } else { 700 ii = 0x21; /* MAX_LOGDRV + 1 - 32 + 1 */ 701 } 702 703 for (cntr = 0; cntr < phy_lun_no; cntr++) { 704 if (rplp->pl_data[cntr].Mode == CISS_PHYS_MODE) { 705 if (cpqary3p->cpqary3_tgtp[ii] == NULL && 706 !(cpqary3p->cpqary3_tgtp[ii] = 707 (cpqary3_tgt_t *) 708 MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) { 709 cmn_err(CE_WARN, "CPQary3 : Failed to Detect " 710 "targets, Memory Allocation Failure"); 711 cpqary3_synccmd_free(cpqary3p, 712 cpqary3_cmdpvtp); 713 return (CPQARY3_FAILURE); 714 } 715 716 bcopy(&(rplp->pl_data[cntr]), 717 &(cpqary3p->cpqary3_tgtp[ii]->PhysID), 718 sizeof (PhysDevAddr_t)); 719 720 cpqary3p->cpqary3_tgtp[ii]->type = CPQARY3_TARGET_TAPE; 721 722 DTRACE_PROBE1(tape_discovered, 723 cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[ii]); 724 725 ii++; 726 } 727 } 728 729 /* Sync Changes */ 730 cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp); 731 /* Sync Changes */ 732 733 return (CPQARY3_SUCCESS); 734 735 } 736 737 /* 738 * Function : cpqary3_synccmd_complete 739 * Description : This routine processes the completed commands 740 * using the sync interface and 741 * initiates any callback that is needed. 742 * Called By : cpqary3_transport 743 * Parameters : per-command 744 * Calls : cpqary3_cmdlist_release, cpqary3_synccmd_cleanup 745 * Return Values: None 746 */ 747 void 748 cpqary3_synccmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp) 749 { 750 cpqary3_t *cpqary3p; 751 752 ASSERT(cpqary3_cmdpvtp != NULL); 753 754 if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) { 755 cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX); 756 return; 757 } 758 759 cpqary3p = cpqary3_cmdpvtp->ctlr; 760 761 if (cpqary3_cmdpvtp->cmdpvt_flag == CPQARY3_SYNC_TIMEOUT) { 762 /* 763 * The submitter has abandoned this command, so we 764 * have to free the resources here. 765 */ 766 mutex_exit(&(cpqary3p->sw_mutex)); 767 cpqary3_synccmd_cleanup(cpqary3_cmdpvtp); 768 mutex_enter(&(cpqary3p->sw_mutex)); 769 } else { 770 /* submitter is waiting; wake him up */ 771 cpqary3_cmdpvtp->cmdpvt_flag = 0; 772 773 /* 774 * Fix for Flush Cache Operation Timed out issue: 775 * cv_signal() wakes up only one blocked thread. 776 * We need to use cv_broadcast which unblocks 777 * all the blocked threads() 778 */ 779 cv_broadcast(&(cpqary3p->cv_ioctl_wait)); 780 } 781 } 782