/* Thread to carry out delayed SCSI-device scanning */ static int rtsx_scan_thread(void *__dev) { struct rtsx_dev *dev = __dev; struct rtsx_chip *chip = dev->chip; /* Wait for the timeout to expire or for a disconnect */ if (delay_use > 0) { dev_info(&dev->pci->dev, "%s: waiting for device to settle before scanning\n", CR_DRIVER_NAME); wait_event_interruptible_timeout(dev->delay_wait, rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), delay_use * HZ); } /* If the device is still connected, perform the scanning */ if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { scsi_scan_host(rtsx_to_host(dev)); dev_info(&dev->pci->dev, "%s: device scan complete\n", CR_DRIVER_NAME); /* Should we unbind if no devices were detected? */ } complete_and_exit(&dev->scanning_done, 0); }
static int rtsx_scan_thread(void * __dev) { struct rtsx_dev *dev = (struct rtsx_dev *)__dev; struct rtsx_chip *chip = dev->chip; if (delay_use > 0) { printk(KERN_INFO "%s: waiting for device " "to settle before scanning\n", CR_DRIVER_NAME); wait_event_interruptible_timeout(dev->delay_wait, rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), delay_use * HZ); } if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { scsi_scan_host(rtsx_to_host(dev)); printk(KERN_INFO "%s: device scan complete\n", CR_DRIVER_NAME); } scsi_host_put(rtsx_to_host(dev)); complete_and_exit(&threads_gone, 0); }
/* This is always called with scsi_lock(host) held */ static int queuecommand_lck(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *)) { struct rtsx_dev *dev = host_to_rtsx(srb->device->host); struct rtsx_chip *chip = dev->chip; /* check for state-transition errors */ if (chip->srb) { dev_err(&dev->pci->dev, "Error: chip->srb = %p\n", chip->srb); return SCSI_MLQUEUE_HOST_BUSY; } /* fail the command if we are disconnecting */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { dev_info(&dev->pci->dev, "Fail command during disconnect\n"); srb->result = DID_NO_CONNECT << 16; done(srb); return 0; } /* enqueue the command and wake up the control thread */ srb->scsi_done = done; chip->srb = srb; complete(&dev->cmnd_ready); return 0; }
static int queuecommand_lck(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *)) { struct rtsx_dev *dev = host_to_rtsx(srb->device->host); struct rtsx_chip *chip = dev->chip; if (chip->srb != NULL) { printk(KERN_ERR "Error in %s: chip->srb = %p\n", __FUNCTION__, chip->srb); return SCSI_MLQUEUE_HOST_BUSY; } if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { printk(KERN_INFO "Fail command during disconnect\n"); srb->result = DID_NO_CONNECT << 16; done(srb); return 0; } srb->scsi_done = done; chip->srb = srb; up(&(dev->sema)); return 0; }
/* This is always called with scsi_lock(host) held */ static int queuecommand_lck(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *)) { struct rtsx_dev *dev = host_to_rtsx(srb->device->host); struct rtsx_chip *chip = dev->chip; /* check for state-transition errors */ if (chip->srb != NULL) { printk(KERN_ERR "Error in %s: chip->srb = %p\n", __func__, chip->srb); return SCSI_MLQUEUE_HOST_BUSY; } /* fail the command if we are disconnecting */ if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { printk(KERN_INFO "Fail command during disconnect\n"); srb->result = DID_NO_CONNECT << 16; done(srb); return 0; } /* enqueue the command and wake up the control thread */ srb->scsi_done = done; chip->srb = srb; up(&(dev->sema)); return 0; }
static int rtsx_polling_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); struct sd_info *sd_card = &(chip->sd_card); struct xd_info *xd_card = &(chip->xd_card); struct ms_info *ms_card = &(chip->ms_card); sd_card->cleanup_counter = 0; xd_card->cleanup_counter = 0; ms_card->cleanup_counter = 0; /* Wait until SCSI scan finished */ wait_timeout((delay_use + 5) * 1000); for (;;) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(POLLING_INTERVAL); /* 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)) { printk(KERN_INFO "-- rtsx-polling exiting\n"); mutex_unlock(&dev->dev_mutex); break; } mutex_unlock(&dev->dev_mutex); mspro_polling_format_status(chip); /* lock the device pointers */ mutex_lock(&(dev->dev_mutex)); rtsx_polling_func(chip); /* unlock the device pointers */ mutex_unlock(&dev->dev_mutex); } scsi_host_put(host); complete_and_exit(&threads_gone, 0); }
static int rtsx_polling_thread(void *__dev) { struct rtsx_dev *dev = __dev; struct rtsx_chip *chip = dev->chip; struct sd_info *sd_card = &chip->sd_card; struct xd_info *xd_card = &chip->xd_card; struct ms_info *ms_card = &chip->ms_card; sd_card->cleanup_counter = 0; xd_card->cleanup_counter = 0; ms_card->cleanup_counter = 0; /* Wait until SCSI scan finished */ wait_timeout((delay_use + 5) * 1000); for (;;) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL)); /* 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-polling exiting\n"); mutex_unlock(&dev->dev_mutex); break; } mutex_unlock(&dev->dev_mutex); mspro_polling_format_status(chip); /* lock the device pointers */ mutex_lock(&dev->dev_mutex); rtsx_polling_func(chip); /* unlock the device pointers */ mutex_unlock(&dev->dev_mutex); } complete_and_exit(&dev->polling_exit, 0); }
static int rtsx_polling_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); struct sd_info *sd_card = &(chip->sd_card); struct xd_info *xd_card = &(chip->xd_card); struct ms_info *ms_card = &(chip->ms_card); sd_card->cleanup_counter = 0; xd_card->cleanup_counter = 0; ms_card->cleanup_counter = 0; wait_timeout((delay_use + 5) * 1000); for(;;) { wait_timeout(POLLING_INTERVAL); mutex_lock(&(dev->dev_mutex)); if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { printk(KERN_INFO "-- rtsx-polling exiting\n"); mutex_unlock(&dev->dev_mutex); break; } mutex_unlock(&dev->dev_mutex); mspro_polling_format_status(chip); mutex_lock(&(dev->dev_mutex)); rtsx_polling_func(chip); mutex_unlock(&dev->dev_mutex); } scsi_host_put(host); 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 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); }