aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
authorMark Haverkamp <markh@linux-foundation.org>2007-03-15 15:55:07 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-03-20 11:54:49 -0400
commitfe76df4235986cfacc2d3b71cef7c42bc1a6dd6c (patch)
treea8b31caeae0d4a60b0271c5e83a0c219de0fde72 /drivers/scsi/aacraid
parenta8166a52968216ae079a5530ac3269147de2ef31 (diff)
[SCSI] aacraid: Fix blocking issue with container probing function (cast update)
Received from Mark Salyzyn, The aac_probe_container call blocks. This is an issue because it is called on occasion in the context of the queuecommand handler. Once in a blue moon this has resulted in a kernel panic sleeping during interrupt; or problems with some embedded system versions of the kernel that depend on queuecommand to not block. This ugly patch rewrites the aac_probe_container call into a new routine _aac_probe_container that is an asynchronous state machine to complete the series of operations. The legacy blocking aac_probe_container call used in other areas of the driver (during initialization scanning for all targets and in the separate hot-add/remove [aacraid] thread) merely issues _aac_probe_container and then simple spins calling schedule() waiting for completion. Signed-off-by: Mark Haverkamp <markh@linux-foundation.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aachba.c311
1 files changed, 169 insertions, 142 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index d789e61bdc49..1610f0670c78 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -258,13 +258,10 @@ int aac_get_containers(struct aac_dev *dev)
258 u32 index; 258 u32 index;
259 int status = 0; 259 int status = 0;
260 struct fib * fibptr; 260 struct fib * fibptr;
261 unsigned instance;
262 struct aac_get_container_count *dinfo; 261 struct aac_get_container_count *dinfo;
263 struct aac_get_container_count_resp *dresp; 262 struct aac_get_container_count_resp *dresp;
264 int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; 263 int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
265 264
266 instance = dev->scsi_host_ptr->unique_id;
267
268 if (!(fibptr = aac_fib_alloc(dev))) 265 if (!(fibptr = aac_fib_alloc(dev)))
269 return -ENOMEM; 266 return -ENOMEM;
270 267
@@ -284,88 +281,35 @@ int aac_get_containers(struct aac_dev *dev)
284 maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); 281 maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
285 aac_fib_complete(fibptr); 282 aac_fib_complete(fibptr);
286 } 283 }
284 aac_fib_free(fibptr);
287 285
288 if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) 286 if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
289 maximum_num_containers = MAXIMUM_NUM_CONTAINERS; 287 maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
290 fsa_dev_ptr = kmalloc( 288 fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
291 sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); 289 GFP_KERNEL);
292 if (!fsa_dev_ptr) { 290 if (!fsa_dev_ptr)
293 aac_fib_free(fibptr);
294 return -ENOMEM; 291 return -ENOMEM;
295 }
296 memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); 292 memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
297 293
298 dev->fsa_dev = fsa_dev_ptr; 294 dev->fsa_dev = fsa_dev_ptr;
299 dev->maximum_num_containers = maximum_num_containers; 295 dev->maximum_num_containers = maximum_num_containers;
300 296
301 for (index = 0; index < dev->maximum_num_containers; index++) { 297 for (index = 0; index < dev->maximum_num_containers; ) {
302 struct aac_query_mount *dinfo;
303 struct aac_mount *dresp;
304
305 fsa_dev_ptr[index].devname[0] = '\0'; 298 fsa_dev_ptr[index].devname[0] = '\0';
306 299
307 aac_fib_init(fibptr); 300 status = aac_probe_container(dev, index);
308 dinfo = (struct aac_query_mount *) fib_data(fibptr);
309
310 dinfo->command = cpu_to_le32(VM_NameServe);
311 dinfo->count = cpu_to_le32(index);
312 dinfo->type = cpu_to_le32(FT_FILESYS);
313 301
314 status = aac_fib_send(ContainerCommand, 302 if (status < 0) {
315 fibptr,
316 sizeof (struct aac_query_mount),
317 FsaNormal,
318 1, 1,
319 NULL, NULL);
320 if (status < 0 ) {
321 printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); 303 printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
322 break; 304 break;
323 } 305 }
324 dresp = (struct aac_mount *)fib_data(fibptr);
325
326 if ((le32_to_cpu(dresp->status) == ST_OK) &&
327 (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
328 dinfo->command = cpu_to_le32(VM_NameServe64);
329 dinfo->count = cpu_to_le32(index);
330 dinfo->type = cpu_to_le32(FT_FILESYS);
331 306
332 if (aac_fib_send(ContainerCommand,
333 fibptr,
334 sizeof(struct aac_query_mount),
335 FsaNormal,
336 1, 1,
337 NULL, NULL) < 0)
338 continue;
339 } else
340 dresp->mnt[0].capacityhigh = 0;
341
342 dprintk ((KERN_DEBUG
343 "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
344 (int)index, (int)le32_to_cpu(dresp->status),
345 (int)le32_to_cpu(dresp->mnt[0].vol),
346 (int)le32_to_cpu(dresp->mnt[0].state),
347 ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
348 (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
349 if ((le32_to_cpu(dresp->status) == ST_OK) &&
350 (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
351 (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
352 fsa_dev_ptr[index].valid = 1;
353 fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
354 fsa_dev_ptr[index].size
355 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
356 (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
357 if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
358 fsa_dev_ptr[index].ro = 1;
359 }
360 aac_fib_complete(fibptr);
361 /* 307 /*
362 * If there are no more containers, then stop asking. 308 * If there are no more containers, then stop asking.
363 */ 309 */
364 if ((index + 1) >= le32_to_cpu(dresp->count)){ 310 if (++index >= status)
365 break; 311 break;
366 }
367 } 312 }
368 aac_fib_free(fibptr);
369 return status; 313 return status;
370} 314}
371 315
@@ -473,85 +417,185 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
473 return -1; 417 return -1;
474} 418}
475 419
476/** 420static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
477 * aac_probe_container - query a logical volume
478 * @dev: device to query
479 * @cid: container identifier
480 *
481 * Queries the controller about the given volume. The volume information
482 * is updated in the struct fsa_dev_info structure rather than returned.
483 */
484
485int aac_probe_container(struct aac_dev *dev, int cid)
486{ 421{
487 struct fsa_dev_info *fsa_dev_ptr; 422 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
488 int status;
489 struct aac_query_mount *dinfo;
490 struct aac_mount *dresp;
491 struct fib * fibptr;
492 unsigned instance;
493 423
494 fsa_dev_ptr = dev->fsa_dev; 424 if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
495 if (!fsa_dev_ptr) 425 return aac_scsi_cmd(scsicmd);
496 return -ENOMEM;
497 instance = dev->scsi_host_ptr->unique_id;
498 426
499 if (!(fibptr = aac_fib_alloc(dev))) 427 scsicmd->result = DID_NO_CONNECT << 16;
500 return -ENOMEM; 428 scsicmd->scsi_done(scsicmd);
429 return 0;
430}
431
432static int _aac_probe_container2(void * context, struct fib * fibptr)
433{
434 struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
435 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
436 int (*callback)(struct scsi_cmnd *);
437
438 scsicmd->SCp.Status = 0;
439 if (fsa_dev_ptr) {
440 struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
441 fsa_dev_ptr += scmd_id(scsicmd);
442
443 if ((le32_to_cpu(dresp->status) == ST_OK) &&
444 (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
445 (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
446 fsa_dev_ptr->valid = 1;
447 fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
448 fsa_dev_ptr->size
449 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
450 (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
451 fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
452 }
453 if ((fsa_dev_ptr->valid & 1) == 0)
454 fsa_dev_ptr->valid = 0;
455 scsicmd->SCp.Status = le32_to_cpu(dresp->count);
456 }
457 aac_fib_complete(fibptr);
458 aac_fib_free(fibptr);
459 callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
460 scsicmd->SCp.ptr = NULL;
461 return (*callback)(scsicmd);
462}
463
464static int _aac_probe_container1(void * context, struct fib * fibptr)
465{
466 struct scsi_cmnd * scsicmd;
467 struct aac_mount * dresp;
468 struct aac_query_mount *dinfo;
469 int status;
470
471 dresp = (struct aac_mount *) fib_data(fibptr);
472 dresp->mnt[0].capacityhigh = 0;
473 if ((le32_to_cpu(dresp->status) != ST_OK) ||
474 ((le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
475 (le32_to_cpu(dresp->mnt[0].state) == FSCS_HIDDEN)))
476 return _aac_probe_container2(context, fibptr);
477 scsicmd = (struct scsi_cmnd *) context;
478 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
501 479
502 aac_fib_init(fibptr); 480 aac_fib_init(fibptr);
503 481
504 dinfo = (struct aac_query_mount *)fib_data(fibptr); 482 dinfo = (struct aac_query_mount *)fib_data(fibptr);
505 483
506 dinfo->command = cpu_to_le32(VM_NameServe); 484 dinfo->command = cpu_to_le32(VM_NameServe64);
507 dinfo->count = cpu_to_le32(cid); 485 dinfo->count = cpu_to_le32(scmd_id(scsicmd));
508 dinfo->type = cpu_to_le32(FT_FILESYS); 486 dinfo->type = cpu_to_le32(FT_FILESYS);
509 487
510 status = aac_fib_send(ContainerCommand, 488 status = aac_fib_send(ContainerCommand,
511 fibptr, 489 fibptr,
512 sizeof(struct aac_query_mount), 490 sizeof(struct aac_query_mount),
513 FsaNormal, 491 FsaNormal,
514 1, 1, 492 0, 1,
515 NULL, NULL); 493 (fib_callback) _aac_probe_container2,
494 (void *) scsicmd);
495 /*
496 * Check that the command queued to the controller
497 */
498 if (status == -EINPROGRESS) {
499 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
500 return 0;
501 }
516 if (status < 0) { 502 if (status < 0) {
517 printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n"); 503 /* Inherit results from VM_NameServe, if any */
518 goto error; 504 dresp->status = cpu_to_le32(ST_OK);
505 return _aac_probe_container2(context, fibptr);
519 } 506 }
507 return 0;
508}
520 509
521 dresp = (struct aac_mount *) fib_data(fibptr); 510static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
511{
512 struct fib * fibptr;
513 int status = -ENOMEM;
522 514
523 if ((le32_to_cpu(dresp->status) == ST_OK) && 515 if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
524 (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { 516 struct aac_query_mount *dinfo;
525 dinfo->command = cpu_to_le32(VM_NameServe64);
526 dinfo->count = cpu_to_le32(cid);
527 dinfo->type = cpu_to_le32(FT_FILESYS);
528 517
529 if (aac_fib_send(ContainerCommand, 518 aac_fib_init(fibptr);
530 fibptr, 519
531 sizeof(struct aac_query_mount), 520 dinfo = (struct aac_query_mount *)fib_data(fibptr);
532 FsaNormal, 521
533 1, 1, 522 dinfo->command = cpu_to_le32(VM_NameServe);
534 NULL, NULL) < 0) 523 dinfo->count = cpu_to_le32(scmd_id(scsicmd));
535 goto error; 524 dinfo->type = cpu_to_le32(FT_FILESYS);
536 } else 525 scsicmd->SCp.ptr = (char *)callback;
537 dresp->mnt[0].capacityhigh = 0;
538 526
539 if ((le32_to_cpu(dresp->status) == ST_OK) && 527 status = aac_fib_send(ContainerCommand,
540 (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && 528 fibptr,
541 (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { 529 sizeof(struct aac_query_mount),
542 fsa_dev_ptr[cid].valid = 1; 530 FsaNormal,
543 fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); 531 0, 1,
544 fsa_dev_ptr[cid].size 532 (fib_callback) _aac_probe_container1,
545 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + 533 (void *) scsicmd);
546 (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); 534 /*
547 if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) 535 * Check that the command queued to the controller
548 fsa_dev_ptr[cid].ro = 1; 536 */
537 if (status == -EINPROGRESS) {
538 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
539 return 0;
540 }
541 if (status < 0) {
542 scsicmd->SCp.ptr = NULL;
543 aac_fib_complete(fibptr);
544 aac_fib_free(fibptr);
545 }
546 }
547 if (status < 0) {
548 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
549 if (fsa_dev_ptr) {
550 fsa_dev_ptr += scmd_id(scsicmd);
551 if ((fsa_dev_ptr->valid & 1) == 0) {
552 fsa_dev_ptr->valid = 0;
553 return (*callback)(scsicmd);
554 }
555 }
549 } 556 }
557 return status;
558}
550 559
551error: 560/**
552 aac_fib_complete(fibptr); 561 * aac_probe_container - query a logical volume
553 aac_fib_free(fibptr); 562 * @dev: device to query
563 * @cid: container identifier
564 *
565 * Queries the controller about the given volume. The volume information
566 * is updated in the struct fsa_dev_info structure rather than returned.
567 */
568static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
569{
570 scsicmd->device = NULL;
571 return 0;
572}
554 573
574int aac_probe_container(struct aac_dev *dev, int cid)
575{
576 struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
577 struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
578 int status;
579
580 if (!scsicmd || !scsidev) {
581 kfree(scsicmd);
582 kfree(scsidev);
583 return -ENOMEM;
584 }
585 scsicmd->list.next = NULL;
586 scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
587
588 scsicmd->device = scsidev;
589 scsidev->sdev_state = 0;
590 scsidev->id = cid;
591 scsidev->host = dev->scsi_host_ptr;
592
593 if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
594 while (scsicmd->device == scsidev)
595 schedule();
596 status = scsicmd->SCp.Status;
597 kfree(scsicmd);
598 kfree(scsidev);
555 return status; 599 return status;
556} 600}
557 601
@@ -1646,29 +1690,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
1646 case TEST_UNIT_READY: 1690 case TEST_UNIT_READY:
1647 if (dev->in_reset) 1691 if (dev->in_reset)
1648 return -1; 1692 return -1;
1649 spin_unlock_irq(host->host_lock); 1693 return _aac_probe_container(scsicmd,
1650 aac_probe_container(dev, cid); 1694 aac_probe_container_callback2);
1651 if ((fsa_dev_ptr[cid].valid & 1) == 0)
1652 fsa_dev_ptr[cid].valid = 0;
1653 spin_lock_irq(host->host_lock);
1654 if (fsa_dev_ptr[cid].valid == 0) {
1655 scsicmd->result = DID_NO_CONNECT << 16;
1656 scsicmd->scsi_done(scsicmd);
1657 return 0;
1658 }
1659 default: 1695 default:
1660 break; 1696 break;
1661 } 1697 }
1662 } 1698 }
1663 /*
1664 * If the target container still doesn't exist,
1665 * return failure
1666 */
1667 if (fsa_dev_ptr[cid].valid == 0) {
1668 scsicmd->result = DID_BAD_TARGET << 16;
1669 scsicmd->scsi_done(scsicmd);
1670 return 0;
1671 }
1672 } else { /* check for physical non-dasd devices */ 1699 } else { /* check for physical non-dasd devices */
1673 if ((dev->nondasd_support == 1) || expose_physicals) { 1700 if ((dev->nondasd_support == 1) || expose_physicals) {
1674 if (dev->in_reset) 1701 if (dev->in_reset)