static int rtsx_control_thread(void * __dev) { struct rtsx_dev *dev = (struct rtsx_dev *)__dev; struct rtsx_chip *chip = dev->chip; struct Scsi_Host *host = rtsx_to_host(dev); current->flags |= PF_NOFREEZE; for(;;) { if(down_interruptible(&dev->sema)) break; mutex_lock(&(dev->dev_mutex)); if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { printk(KERN_INFO "-- rtsx-control exiting\n"); mutex_unlock(&dev->dev_mutex); break; } scsi_lock(host); if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { chip->srb->result = DID_ABORT << 16; goto SkipForAbort; } scsi_unlock(host); /* reject the command if the direction indicator * is UNKNOWN */ if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { printk(KERN_ERR "UNKNOWN data direction\n"); chip->srb->result = DID_ERROR << 16; } /* reject if target != 0 or if LUN is higher than * the maximum known LUN */ else if (chip->srb->device->id) { printk(KERN_ERR "Bad target number (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else if (chip->srb->device->lun > chip->max_lun) { printk(KERN_ERR "Bad LUN (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else { RTSX_DEBUG(scsi_show_command(chip->srb)); rtsx_invoke_transport(chip->srb, chip); } scsi_lock(host); if (!chip->srb) ; else if (chip->srb->result != DID_ABORT << 16) { chip->srb->scsi_done(chip->srb); } else { SkipForAbort: printk(KERN_ERR "scsi command aborted\n"); } if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { complete(&(dev->notify)); rtsx_set_stat(chip, RTSX_STAT_IDLE); } chip->srb = NULL; scsi_unlock(host); mutex_unlock(&dev->dev_mutex); } scsi_host_put(host); /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ complete_and_exit(&threads_gone, 0); }
static int rtsx_control_thread(void *__dev) { struct rtsx_dev *dev = __dev; struct rtsx_chip *chip = dev->chip; struct Scsi_Host *host = rtsx_to_host(dev); for (;;) { if (wait_for_completion_interruptible(&dev->cmnd_ready)) break; /* lock the device pointers */ mutex_lock(&(dev->dev_mutex)); /* if the device has disconnected, we are free to exit */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { dev_info(&dev->pci->dev, "-- rtsx-control exiting\n"); mutex_unlock(&dev->dev_mutex); break; } /* lock access to the state */ scsi_lock(host); /* has the command aborted ? */ if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { chip->srb->result = DID_ABORT << 16; goto SkipForAbort; } scsi_unlock(host); /* reject the command if the direction indicator * is UNKNOWN */ if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { dev_err(&dev->pci->dev, "UNKNOWN data direction\n"); chip->srb->result = DID_ERROR << 16; } /* reject if target != 0 or if LUN is higher than * the maximum known LUN */ else if (chip->srb->device->id) { dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", chip->srb->device->id, (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else if (chip->srb->device->lun > chip->max_lun) { dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", chip->srb->device->id, (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } /* we've got a command, let's do it! */ else { scsi_show_command(chip); rtsx_invoke_transport(chip->srb, chip); } /* lock access to the state */ scsi_lock(host); /* did the command already complete because of a disconnect? */ if (!chip->srb) ; /* nothing to do */ /* indicate that the command is done */ else if (chip->srb->result != DID_ABORT << 16) { chip->srb->scsi_done(chip->srb); } else { SkipForAbort: dev_err(&dev->pci->dev, "scsi command aborted\n"); } if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { complete(&(dev->notify)); rtsx_set_stat(chip, RTSX_STAT_IDLE); } /* finished working on this command */ chip->srb = NULL; scsi_unlock(host); /* unlock the device pointers */ mutex_unlock(&dev->dev_mutex); } /* for (;;) */ /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ complete_and_exit(&dev->control_exit, 0); }
static int rts51x_control_thread(void *__chip) { struct rts51x_chip *chip = (struct rts51x_chip *)__chip; struct Scsi_Host *host = rts51x_to_host(chip); for (;;) { if (wait_for_completion_interruptible(&chip->usb->cmnd_ready)) break; if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { RTS51X_DEBUGP("-- exiting from rts51x-control\n"); break; } mutex_lock(&(chip->usb->dev_mutex)); scsi_lock(host); if (chip->srb == NULL) { scsi_unlock(host); mutex_unlock(&chip->usb->dev_mutex); RTS51X_DEBUGP("-- exiting from control thread\n"); break; } if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { chip->srb->result = DID_ABORT << 16; goto SkipForAbort; } scsi_unlock(host); if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { RTS51X_DEBUGP("UNKNOWN data direction\n"); chip->srb->result = DID_ERROR << 16; } else if (chip->srb->device->id) { RTS51X_DEBUGP("Bad target number (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else if (chip->srb->device->lun > chip->max_lun) { RTS51X_DEBUGP("Bad LUN (%d:%d)\n", chip->srb->device->id, chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else { RTS51X_DEBUG(scsi_show_command(chip->srb)); rts51x_invoke_transport(chip->srb, chip); } scsi_lock(host); if (chip->srb->result != DID_ABORT << 16) chip->srb->scsi_done(chip->srb); else SkipForAbort : RTS51X_DEBUGP("scsi command aborted\n"); if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { complete(&(chip->usb->notify)); clear_bit(FLIDX_ABORTING, &chip->usb->dflags); clear_bit(FLIDX_TIMED_OUT, &chip->usb->dflags); } chip->srb = NULL; scsi_unlock(host); mutex_unlock(&chip->usb->dev_mutex); } complete(&chip->usb->control_exit); return 0; }