Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.12-rc2 650 lines 23 kB view raw
1/* gdth_proc.c 2 * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $ 3 */ 4 5#include <linux/completion.h> 6#include <linux/slab.h> 7 8int gdth_set_info(struct Scsi_Host *host, char *buffer, int length) 9{ 10 gdth_ha_str *ha = shost_priv(host); 11 int ret_val = -EINVAL; 12 13 TRACE2(("gdth_set_info() ha %d\n",ha->hanum,)); 14 15 if (length >= 4) { 16 if (strncmp(buffer,"gdth",4) == 0) { 17 buffer += 5; 18 length -= 5; 19 ret_val = gdth_set_asc_info(host, buffer, length, ha); 20 } 21 } 22 23 return ret_val; 24} 25 26static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, 27 int length, gdth_ha_str *ha) 28{ 29 int orig_length, drive, wb_mode; 30 int i, found; 31 gdth_cmd_str gdtcmd; 32 gdth_cpar_str *pcpar; 33 u64 paddr; 34 35 char cmnd[MAX_COMMAND_SIZE]; 36 memset(cmnd, 0xff, 12); 37 memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); 38 39 TRACE2(("gdth_set_asc_info() ha %d\n",ha->hanum)); 40 orig_length = length + 5; 41 drive = -1; 42 wb_mode = 0; 43 found = FALSE; 44 45 if (length >= 5 && strncmp(buffer,"flush",5)==0) { 46 buffer += 6; 47 length -= 6; 48 if (length && *buffer>='0' && *buffer<='9') { 49 drive = (int)(*buffer-'0'); 50 ++buffer; --length; 51 if (length && *buffer>='0' && *buffer<='9') { 52 drive = drive*10 + (int)(*buffer-'0'); 53 ++buffer; --length; 54 } 55 printk("GDT: Flushing host drive %d .. ",drive); 56 } else { 57 printk("GDT: Flushing all host drives .. "); 58 } 59 for (i = 0; i < MAX_HDRIVES; ++i) { 60 if (ha->hdr[i].present) { 61 if (drive != -1 && i != drive) 62 continue; 63 found = TRUE; 64 gdtcmd.Service = CACHESERVICE; 65 gdtcmd.OpCode = GDT_FLUSH; 66 if (ha->cache_feat & GDT_64BIT) { 67 gdtcmd.u.cache64.DeviceNo = i; 68 gdtcmd.u.cache64.BlockNo = 1; 69 } else { 70 gdtcmd.u.cache.DeviceNo = i; 71 gdtcmd.u.cache.BlockNo = 1; 72 } 73 74 gdth_execute(host, &gdtcmd, cmnd, 30, NULL); 75 } 76 } 77 if (!found) 78 printk("\nNo host drive found !\n"); 79 else 80 printk("Done.\n"); 81 return(orig_length); 82 } 83 84 if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) { 85 buffer += 8; 86 length -= 8; 87 printk("GDT: Disabling write back permanently .. "); 88 wb_mode = 1; 89 } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) { 90 buffer += 7; 91 length -= 7; 92 printk("GDT: Enabling write back permanently .. "); 93 wb_mode = 2; 94 } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) { 95 buffer += 7; 96 length -= 7; 97 printk("GDT: Disabling write back commands .. "); 98 if (ha->cache_feat & GDT_WR_THROUGH) { 99 gdth_write_through = TRUE; 100 printk("Done.\n"); 101 } else { 102 printk("Not supported !\n"); 103 } 104 return(orig_length); 105 } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) { 106 buffer += 6; 107 length -= 6; 108 printk("GDT: Enabling write back commands .. "); 109 gdth_write_through = FALSE; 110 printk("Done.\n"); 111 return(orig_length); 112 } 113 114 if (wb_mode) { 115 if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr)) 116 return(-EBUSY); 117 pcpar = (gdth_cpar_str *)ha->pscratch; 118 memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); 119 gdtcmd.Service = CACHESERVICE; 120 gdtcmd.OpCode = GDT_IOCTL; 121 gdtcmd.u.ioctl.p_param = paddr; 122 gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str); 123 gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; 124 gdtcmd.u.ioctl.channel = INVALID_CHANNEL; 125 pcpar->write_back = wb_mode==1 ? 0:1; 126 127 gdth_execute(host, &gdtcmd, cmnd, 30, NULL); 128 129 gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr); 130 printk("Done.\n"); 131 return(orig_length); 132 } 133 134 printk("GDT: Unknown command: %s Length: %d\n",buffer,length); 135 return(-EINVAL); 136} 137 138int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) 139{ 140 gdth_ha_str *ha = shost_priv(host); 141 int hlen; 142 int id, i, j, k, sec, flag; 143 int no_mdrv = 0, drv_no, is_mirr; 144 u32 cnt; 145 u64 paddr; 146 int rc = -ENOMEM; 147 148 gdth_cmd_str *gdtcmd; 149 gdth_evt_str *estr; 150 char hrec[161]; 151 152 char *buf; 153 gdth_dskstat_str *pds; 154 gdth_diskinfo_str *pdi; 155 gdth_arrayinf_str *pai; 156 gdth_defcnt_str *pdef; 157 gdth_cdrinfo_str *pcdi; 158 gdth_hget_str *phg; 159 char cmnd[MAX_COMMAND_SIZE]; 160 161 gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL); 162 estr = kmalloc(sizeof(*estr), GFP_KERNEL); 163 if (!gdtcmd || !estr) 164 goto free_fail; 165 166 memset(cmnd, 0xff, 12); 167 memset(gdtcmd, 0, sizeof(gdth_cmd_str)); 168 169 TRACE2(("gdth_get_info() ha %d\n",ha->hanum)); 170 171 172 /* request is i.e. "cat /proc/scsi/gdth/0" */ 173 /* format: %-15s\t%-10s\t%-15s\t%s */ 174 /* driver parameters */ 175 seq_puts(m, "Driver Parameters:\n"); 176 if (reserve_list[0] == 0xff) 177 strcpy(hrec, "--"); 178 else { 179 hlen = sprintf(hrec, "%d", reserve_list[0]); 180 for (i = 1; i < MAX_RES_ARGS; i++) { 181 if (reserve_list[i] == 0xff) 182 break; 183 hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]); 184 } 185 } 186 seq_printf(m, 187 " reserve_mode: \t%d \treserve_list: \t%s\n", 188 reserve_mode, hrec); 189 seq_printf(m, 190 " max_ids: \t%-3d \thdr_channel: \t%d\n", 191 max_ids, hdr_channel); 192 193 /* controller information */ 194 seq_puts(m, "\nDisk Array Controller Information:\n"); 195 seq_printf(m, 196 " Number: \t%d \tName: \t%s\n", 197 ha->hanum, ha->binfo.type_string); 198 199 seq_printf(m, 200 " Driver Ver.: \t%-10s\tFirmware Ver.: \t", 201 GDTH_VERSION_STR); 202 if (ha->more_proc) 203 seq_printf(m, "%d.%02d.%02d-%c%03X\n", 204 (u8)(ha->binfo.upd_fw_ver>>24), 205 (u8)(ha->binfo.upd_fw_ver>>16), 206 (u8)(ha->binfo.upd_fw_ver), 207 ha->bfeat.raid ? 'R':'N', 208 ha->binfo.upd_revision); 209 else 210 seq_printf(m, "%d.%02d\n", (u8)(ha->cpar.version>>8), 211 (u8)(ha->cpar.version)); 212 213 if (ha->more_proc) 214 /* more information: 1. about controller */ 215 seq_printf(m, 216 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", 217 ha->binfo.ser_no, ha->binfo.memsize / 1024); 218 219#ifdef GDTH_DMA_STATISTICS 220 /* controller statistics */ 221 seq_puts(m, "\nController Statistics:\n"); 222 seq_printf(m, 223 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n", 224 ha->dma32_cnt, ha->dma64_cnt); 225#endif 226 227 if (ha->more_proc) { 228 /* more information: 2. about physical devices */ 229 seq_puts(m, "\nPhysical Devices:"); 230 flag = FALSE; 231 232 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 233 if (!buf) 234 goto stop_output; 235 for (i = 0; i < ha->bus_cnt; ++i) { 236 /* 2.a statistics (and retries/reassigns) */ 237 TRACE2(("pdr_statistics() chn %d\n",i)); 238 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); 239 gdtcmd->Service = CACHESERVICE; 240 gdtcmd->OpCode = GDT_IOCTL; 241 gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4; 242 gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4; 243 gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; 244 gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; 245 pds->bid = ha->raw[i].local_no; 246 pds->first = 0; 247 pds->entries = ha->raw[i].pdev_cnt; 248 cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(u32)) / 249 sizeof(pds->list[0]); 250 if (pds->entries > cnt) 251 pds->entries = cnt; 252 253 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 254 pds->count = 0; 255 256 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ 257 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { 258 /* 2.b drive info */ 259 TRACE2(("scsi_drv_info() chn %d dev %d\n", 260 i, ha->raw[i].id_list[j])); 261 pdi = (gdth_diskinfo_str *)buf; 262 gdtcmd->Service = CACHESERVICE; 263 gdtcmd->OpCode = GDT_IOCTL; 264 gdtcmd->u.ioctl.p_param = paddr; 265 gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str); 266 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; 267 gdtcmd->u.ioctl.channel = 268 ha->raw[i].address | ha->raw[i].id_list[j]; 269 270 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 271 strncpy(hrec,pdi->vendor,8); 272 strncpy(hrec+8,pdi->product,16); 273 strncpy(hrec+24,pdi->revision,4); 274 hrec[28] = 0; 275 seq_printf(m, 276 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", 277 'A'+i,pdi->target_id,pdi->lun,hrec); 278 flag = TRUE; 279 pdi->no_ldrive &= 0xffff; 280 if (pdi->no_ldrive == 0xffff) 281 strcpy(hrec,"--"); 282 else 283 sprintf(hrec,"%d",pdi->no_ldrive); 284 seq_printf(m, 285 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", 286 pdi->blkcnt/(1024*1024/pdi->blksize), 287 hrec); 288 } else { 289 pdi->devtype = 0xff; 290 } 291 292 if (pdi->devtype == 0) { 293 /* search retries/reassigns */ 294 for (k = 0; k < pds->count; ++k) { 295 if (pds->list[k].tid == pdi->target_id && 296 pds->list[k].lun == pdi->lun) { 297 seq_printf(m, 298 " Retries: \t%-6d \tReassigns: \t%d\n", 299 pds->list[k].retries, 300 pds->list[k].reassigns); 301 break; 302 } 303 } 304 /* 2.c grown defects */ 305 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", 306 i, ha->raw[i].id_list[j])); 307 pdef = (gdth_defcnt_str *)buf; 308 gdtcmd->Service = CACHESERVICE; 309 gdtcmd->OpCode = GDT_IOCTL; 310 gdtcmd->u.ioctl.p_param = paddr; 311 gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str); 312 gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; 313 gdtcmd->u.ioctl.channel = 314 ha->raw[i].address | ha->raw[i].id_list[j]; 315 pdef->sddc_type = 0x08; 316 317 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 318 seq_printf(m, 319 " Grown Defects:\t%d\n", 320 pdef->sddc_cnt); 321 } 322 } 323 } 324 } 325 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 326 327 if (!flag) 328 seq_puts(m, "\n --\n"); 329 330 /* 3. about logical drives */ 331 seq_puts(m, "\nLogical Drives:"); 332 flag = FALSE; 333 334 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 335 if (!buf) 336 goto stop_output; 337 for (i = 0; i < MAX_LDRIVES; ++i) { 338 if (!ha->hdr[i].is_logdrv) 339 continue; 340 drv_no = i; 341 j = k = 0; 342 is_mirr = FALSE; 343 do { 344 /* 3.a log. drive info */ 345 TRACE2(("cache_drv_info() drive no %d\n",drv_no)); 346 pcdi = (gdth_cdrinfo_str *)buf; 347 gdtcmd->Service = CACHESERVICE; 348 gdtcmd->OpCode = GDT_IOCTL; 349 gdtcmd->u.ioctl.p_param = paddr; 350 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str); 351 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO; 352 gdtcmd->u.ioctl.channel = drv_no; 353 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 354 break; 355 pcdi->ld_dtype >>= 16; 356 j++; 357 if (pcdi->ld_dtype > 2) { 358 strcpy(hrec, "missing"); 359 } else if (pcdi->ld_error & 1) { 360 strcpy(hrec, "fault"); 361 } else if (pcdi->ld_error & 2) { 362 strcpy(hrec, "invalid"); 363 k++; j--; 364 } else { 365 strcpy(hrec, "ok"); 366 } 367 368 if (drv_no == i) { 369 seq_printf(m, 370 "\n Number: \t%-2d \tStatus: \t%s\n", 371 drv_no, hrec); 372 flag = TRUE; 373 no_mdrv = pcdi->cd_ldcnt; 374 if (no_mdrv > 1 || pcdi->ld_slave != -1) { 375 is_mirr = TRUE; 376 strcpy(hrec, "RAID-1"); 377 } else if (pcdi->ld_dtype == 0) { 378 strcpy(hrec, "Disk"); 379 } else if (pcdi->ld_dtype == 1) { 380 strcpy(hrec, "RAID-0"); 381 } else if (pcdi->ld_dtype == 2) { 382 strcpy(hrec, "Chain"); 383 } else { 384 strcpy(hrec, "???"); 385 } 386 seq_printf(m, 387 " Capacity [MB]:\t%-6d \tType: \t%s\n", 388 pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), 389 hrec); 390 } else { 391 seq_printf(m, 392 " Slave Number: \t%-2d \tStatus: \t%s\n", 393 drv_no & 0x7fff, hrec); 394 } 395 drv_no = pcdi->ld_slave; 396 } while (drv_no != -1); 397 398 if (is_mirr) 399 seq_printf(m, 400 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", 401 no_mdrv - j - k, k); 402 403 if (!ha->hdr[i].is_arraydrv) 404 strcpy(hrec, "--"); 405 else 406 sprintf(hrec, "%d", ha->hdr[i].master_no); 407 seq_printf(m, 408 " To Array Drv.:\t%s\n", hrec); 409 } 410 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 411 412 if (!flag) 413 seq_puts(m, "\n --\n"); 414 415 /* 4. about array drives */ 416 seq_puts(m, "\nArray Drives:"); 417 flag = FALSE; 418 419 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 420 if (!buf) 421 goto stop_output; 422 for (i = 0; i < MAX_LDRIVES; ++i) { 423 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) 424 continue; 425 /* 4.a array drive info */ 426 TRACE2(("array_info() drive no %d\n",i)); 427 pai = (gdth_arrayinf_str *)buf; 428 gdtcmd->Service = CACHESERVICE; 429 gdtcmd->OpCode = GDT_IOCTL; 430 gdtcmd->u.ioctl.p_param = paddr; 431 gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str); 432 gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; 433 gdtcmd->u.ioctl.channel = i; 434 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 435 if (pai->ai_state == 0) 436 strcpy(hrec, "idle"); 437 else if (pai->ai_state == 2) 438 strcpy(hrec, "build"); 439 else if (pai->ai_state == 4) 440 strcpy(hrec, "ready"); 441 else if (pai->ai_state == 6) 442 strcpy(hrec, "fail"); 443 else if (pai->ai_state == 8 || pai->ai_state == 10) 444 strcpy(hrec, "rebuild"); 445 else 446 strcpy(hrec, "error"); 447 if (pai->ai_ext_state & 0x10) 448 strcat(hrec, "/expand"); 449 else if (pai->ai_ext_state & 0x1) 450 strcat(hrec, "/patch"); 451 seq_printf(m, 452 "\n Number: \t%-2d \tStatus: \t%s\n", 453 i,hrec); 454 flag = TRUE; 455 456 if (pai->ai_type == 0) 457 strcpy(hrec, "RAID-0"); 458 else if (pai->ai_type == 4) 459 strcpy(hrec, "RAID-4"); 460 else if (pai->ai_type == 5) 461 strcpy(hrec, "RAID-5"); 462 else 463 strcpy(hrec, "RAID-10"); 464 seq_printf(m, 465 " Capacity [MB]:\t%-6d \tType: \t%s\n", 466 pai->ai_size/(1024*1024/pai->ai_secsize), 467 hrec); 468 } 469 } 470 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 471 472 if (!flag) 473 seq_puts(m, "\n --\n"); 474 475 /* 5. about host drives */ 476 seq_puts(m, "\nHost Drives:"); 477 flag = FALSE; 478 479 buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr); 480 if (!buf) 481 goto stop_output; 482 for (i = 0; i < MAX_LDRIVES; ++i) { 483 if (!ha->hdr[i].is_logdrv || 484 (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) 485 continue; 486 /* 5.a get host drive list */ 487 TRACE2(("host_get() drv_no %d\n",i)); 488 phg = (gdth_hget_str *)buf; 489 gdtcmd->Service = CACHESERVICE; 490 gdtcmd->OpCode = GDT_IOCTL; 491 gdtcmd->u.ioctl.p_param = paddr; 492 gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str); 493 gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; 494 gdtcmd->u.ioctl.channel = i; 495 phg->entries = MAX_HDRIVES; 496 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 497 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 498 ha->hdr[i].ldr_no = i; 499 ha->hdr[i].rw_attribs = 0; 500 ha->hdr[i].start_sec = 0; 501 } else { 502 for (j = 0; j < phg->entries; ++j) { 503 k = phg->entry[j].host_drive; 504 if (k >= MAX_LDRIVES) 505 continue; 506 ha->hdr[k].ldr_no = phg->entry[j].log_drive; 507 ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; 508 ha->hdr[k].start_sec = phg->entry[j].start_sec; 509 } 510 } 511 } 512 gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr); 513 514 for (i = 0; i < MAX_HDRIVES; ++i) { 515 if (!(ha->hdr[i].present)) 516 continue; 517 518 seq_printf(m, 519 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", 520 i, ha->hdr[i].ldr_no); 521 flag = TRUE; 522 523 seq_printf(m, 524 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", 525 (u32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec); 526 } 527 528 if (!flag) 529 seq_puts(m, "\n --\n"); 530 } 531 532 /* controller events */ 533 seq_puts(m, "\nController Events:\n"); 534 535 for (id = -1;;) { 536 id = gdth_read_event(ha, id, estr); 537 if (estr->event_source == 0) 538 break; 539 if (estr->event_data.eu.driver.ionode == ha->hanum && 540 estr->event_source == ES_ASYNC) { 541 gdth_log_event(&estr->event_data, hrec); 542 543 /* 544 * Elapsed seconds subtraction with unsigned operands is 545 * safe from wrap around in year 2106. Executes as: 546 * operand a + (2's complement operand b) + 1 547 */ 548 549 sec = (int)((u32)ktime_get_real_seconds() - estr->first_stamp); 550 if (sec < 0) sec = 0; 551 seq_printf(m," date- %02d:%02d:%02d\t%s\n", 552 sec/3600, sec%3600/60, sec%60, hrec); 553 } 554 if (id == -1) 555 break; 556 } 557stop_output: 558 rc = 0; 559free_fail: 560 kfree(gdtcmd); 561 kfree(estr); 562 return rc; 563} 564 565static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, 566 u64 *paddr) 567{ 568 unsigned long flags; 569 char *ret_val; 570 571 if (size == 0) 572 return NULL; 573 574 spin_lock_irqsave(&ha->smp_lock, flags); 575 576 if (!ha->scratch_busy && size <= GDTH_SCRATCH) { 577 ha->scratch_busy = TRUE; 578 ret_val = ha->pscratch; 579 *paddr = ha->scratch_phys; 580 } else if (scratch) { 581 ret_val = NULL; 582 } else { 583 dma_addr_t dma_addr; 584 585 ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); 586 *paddr = dma_addr; 587 } 588 589 spin_unlock_irqrestore(&ha->smp_lock, flags); 590 return ret_val; 591} 592 593static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, u64 paddr) 594{ 595 unsigned long flags; 596 597 if (buf == ha->pscratch) { 598 spin_lock_irqsave(&ha->smp_lock, flags); 599 ha->scratch_busy = FALSE; 600 spin_unlock_irqrestore(&ha->smp_lock, flags); 601 } else { 602 pci_free_consistent(ha->pdev, size, buf, paddr); 603 } 604} 605 606#ifdef GDTH_IOCTL_PROC 607static int gdth_ioctl_check_bin(gdth_ha_str *ha, u16 size) 608{ 609 unsigned long flags; 610 int ret_val; 611 612 spin_lock_irqsave(&ha->smp_lock, flags); 613 614 ret_val = FALSE; 615 if (ha->scratch_busy) { 616 if (((gdth_iord_str *)ha->pscratch)->size == (u32)size) 617 ret_val = TRUE; 618 } 619 spin_unlock_irqrestore(&ha->smp_lock, flags); 620 return ret_val; 621} 622#endif 623 624static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) 625{ 626 unsigned long flags; 627 int i; 628 Scsi_Cmnd *scp; 629 struct gdth_cmndinfo *cmndinfo; 630 u8 b, t; 631 632 spin_lock_irqsave(&ha->smp_lock, flags); 633 634 for (i = 0; i < GDTH_MAXCMDS; ++i) { 635 scp = ha->cmd_tab[i].cmnd; 636 cmndinfo = gdth_cmnd_priv(scp); 637 638 b = scp->device->channel; 639 t = scp->device->id; 640 if (!SPECIAL_SCP(scp) && t == (u8)id && 641 b == (u8)busnum) { 642 cmndinfo->wait_for_completion = 0; 643 spin_unlock_irqrestore(&ha->smp_lock, flags); 644 while (!cmndinfo->wait_for_completion) 645 barrier(); 646 spin_lock_irqsave(&ha->smp_lock, flags); 647 } 648 } 649 spin_unlock_irqrestore(&ha->smp_lock, flags); 650}