Esempio n. 1
0
/* 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);
}
Esempio n. 2
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);
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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);
}
Esempio n. 7
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);
}
Esempio n. 8
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);
}
Esempio n. 9
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);
}
Esempio n. 10
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);
}