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

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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值