Linux那些事儿之我是Block层(9)scsi命令的前世今生(三) – fudan

459 /*

460 * Function: scsi_dispatch_command

461 *

462 * Purpose: Dispatch a command to the low-level driver.

463 *

464 * Arguments: cmd – command block we are dispatching.

465 *

466 * Notes:

467 */

468 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)

469 {

470 struct Scsi_Host *host = cmd->device->host;

471 unsigned long flags = 0;

472 unsigned long timeout;

473 int rtn = 0;

474

475 /* check if the device is still usable */

476 if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {

477 /* in SDEV_DEL we error all commands. DID_NO_CONNECT

478 * returns an immediate error upwards, and signals

479 * that the device is no longer present */

480 cmd->result = DID_NO_CONNECT << 16;

481 atomic_inc(&cmd->device->iorequest_cnt);

482 __scsi_done(cmd);

483 /* return 0 (because the command has been processed) */

484 goto out;

485 }

486

487 /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */

488 if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {

489 /*

490 * in SDEV_BLOCK, the command is just put back on the device

491 * queue. The suspend state has already blocked the queue so

492 * future requests should not occur until the device

493 * transitions out of the suspend state.

494 */

495 scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);

496

497 SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked /n"));

498

499 /*

500 * NOTE: rtn is still zero here because we don’t need the

501 * queue to be plugged on return (it’s already stopped)

502 */

503 goto out;

504 }

505

506 /*

507 * If SCSI-2 or lower, store the LUN value in cmnd.

508 */

509 if (cmd->device->scsi_level <= SCSI_2 &&

510 cmd->device->scsi_level != SCSI_UNKNOWN) {

511 cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |

512 (cmd->device->lun << 5 & 0xe0);

513 }

514

515 /*

516 * We will wait MIN_RESET_DELAY clock ticks after the last reset so

517 * we can avoid the drive not being ready.

518 */

519 timeout = host->last_reset + MIN_RESET_DELAY;

520

521 if (host->resetting && time_before(jiffies, timeout)) {

522 int ticks_remaining = timeout – jiffies;

523 /*

524 * NOTE: This may be executed from within an interrupt

525 * handler! This is bad, but for now, it’ll do. The irq

526 * level of the interrupt handler has been masked out by the

527 * platform dependent interrupt handling code already, so the

528 * sti() here will not cause another call to the SCSI host’s

529 * interrupt handler (assuming there is one irq-level per

530 * host).

531 */

532 while (–ticks_remaining >= 0)

533 mdelay(1 + 999 / HZ);

534 host->resetting = 0;

535 }

536

537 /*

538 * AK: unlikely race here: for some reason the timer could

539 * expire before the serial number is set up below.

540 */

541 scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);

542

543 scsi_log_send(cmd);

544

545 /*

546 * We will use a queued command if possible, otherwise we will

547 * emulate the queuing and calling of completion function ourselves.

548 */

549 atomic_inc(&cmd->device->iorequest_cnt);

550

551 /*

552 * Before we queue this command, check if the command

553 * length exceeds what the host adapter can handle.

554 */

555 if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {

556 SCSI_LOG_MLQUEUE(3,

557 printk("queuecommand : command too long./n"));

558 cmd->result = (DID_ABORT << 16);

559

560 scsi_done(cmd);

561 goto out;

562 }

563

564 spin_lock_irqsave(host->host_lock, flags);

565 scsi_cmd_get_serial(host, cmd);

566

567 if (unlikely(host->shost_state == SHOST_DEL)) {

568 cmd->result = (DID_NO_CONNECT << 16);

569 scsi_done(cmd);

570 } else {

571 rtn = host->hostt->queuecommand(cmd, scsi_done);

572 }

573 spin_unlock_irqrestore(host->host_lock, flags);

574 if (rtn) {

575 if (scsi_delete_timer(cmd)) {

576 atomic_inc(&cmd->device->iodone_cnt);

577 scsi_queue_insert(cmd,

578 (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?

579 rtn : SCSI_MLQUEUE_HOST_BUSY);

580 }

581 SCSI_LOG_MLQUEUE(3,

582 printk("queuecommand : request rejected/n"));

583 }

584

585 out:

586 SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()/n"));

587 return rtn;

588 }

『 不可能 』只存在於蠢人的字典里

Linux那些事儿之我是Block层(9)scsi命令的前世今生(三) – fudan

相关文章:

你感兴趣的文章:

标签云: