void do_remaining_work(struct rtsx_chip *chip) { struct sd_info *sd_card = &(chip->sd_card); #ifdef XD_DELAY_WRITE struct xd_info *xd_card = &(chip->xd_card); #endif struct ms_info *ms_card = &(chip->ms_card); if (chip->card_ready & SD_CARD) { if (sd_card->seq_mode) { rtsx_set_stat(chip, RTSX_STAT_RUN); sd_card->cleanup_counter ++; } else { sd_card->cleanup_counter = 0; } } #ifdef XD_DELAY_WRITE if (chip->card_ready & XD_CARD) { if (xd_card->delay_write.delay_write_flag) { rtsx_set_stat(chip, RTSX_STAT_RUN); xd_card->cleanup_counter ++; } else { xd_card->cleanup_counter = 0; } } #endif if (chip->card_ready & MS_CARD) { if (CHK_MSPRO(ms_card)) { if (ms_card->seq_mode) { rtsx_set_stat(chip, RTSX_STAT_RUN); ms_card->cleanup_counter ++; } else { ms_card->cleanup_counter = 0; } } else { #ifdef MS_DELAY_WRITE if (ms_card->delay_write.delay_write_flag) { rtsx_set_stat(chip, RTSX_STAT_RUN); ms_card->cleanup_counter ++; } else { ms_card->cleanup_counter = 0; } #endif } } if (sd_card->cleanup_counter > POLLING_WAIT_CNT) { sd_cleanup_work(chip); } if (xd_card->cleanup_counter > POLLING_WAIT_CNT) { xd_cleanup_work(chip); } if (ms_card->cleanup_counter > POLLING_WAIT_CNT) { ms_cleanup_work(chip); } }
/* Command timeout and abort */ static int command_abort(struct scsi_cmnd *srb) { struct Scsi_Host *host = srb->device->host; struct rtsx_dev *dev = host_to_rtsx(host); struct rtsx_chip *chip = dev->chip; dev_info(&dev->pci->dev, "%s called\n", __func__); scsi_lock(host); /* Is this command still active? */ if (chip->srb != srb) { scsi_unlock(host); dev_info(&dev->pci->dev, "-- nothing to abort\n"); return FAILED; } rtsx_set_stat(chip, RTSX_STAT_ABORT); scsi_unlock(host); /* Wait for the aborted command to finish */ wait_for_completion(&dev->notify); return SUCCESS; }
/* First stage of disconnect processing: stop all commands and remove * the host */ static void quiesce_and_remove_host(struct rtsx_dev *dev) { struct Scsi_Host *host = rtsx_to_host(dev); struct rtsx_chip *chip = dev->chip; /* Prevent new transfers, stop the current command, and * interrupt a SCSI-scan or device-reset delay */ mutex_lock(&dev->dev_mutex); scsi_lock(host); rtsx_set_stat(chip, RTSX_STAT_DISCONNECT); scsi_unlock(host); mutex_unlock(&dev->dev_mutex); wake_up(&dev->delay_wait); wait_for_completion(&dev->scanning_done); /* Wait some time to let other threads exist */ wait_timeout(100); /* queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there * is such a command pending, complete it with an error. */ mutex_lock(&dev->dev_mutex); if (chip->srb) { chip->srb->result = DID_NO_CONNECT << 16; scsi_lock(host); chip->srb->scsi_done(dev->chip->srb); chip->srb = NULL; scsi_unlock(host); } mutex_unlock(&dev->dev_mutex); /* Now we own no commands so it's safe to remove the SCSI host */ scsi_remove_host(host); }
static int command_abort(struct scsi_cmnd *srb) { struct Scsi_Host *host = srb->device->host; struct rtsx_dev *dev = host_to_rtsx(host); struct rtsx_chip *chip = dev->chip; printk(KERN_INFO "%s called\n", __FUNCTION__); scsi_lock(host); if (chip->srb != srb) { scsi_unlock(host); printk(KERN_INFO "-- nothing to abort\n"); return FAILED; } rtsx_set_stat(chip, RTSX_STAT_ABORT); scsi_unlock(host); wait_for_completion(&dev->notify); return SUCCESS; }
void do_reset_sd_card(struct rtsx_chip *chip) { int retval; RTSX_DEBUGP(("%s: %d, card2lun = 0x%x\n", __FUNCTION__, chip->sd_reset_counter, chip->card2lun[SD_CARD])); if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) { clear_bit(SD_NR, &(chip->need_reset)); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; return; } chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; rtsx_set_stat(chip, RTSX_STAT_RUN); rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); retval = reset_sd_card(chip); if (chip->need_release & SD_CARD) { return; } if (retval == STATUS_SUCCESS) { clear_bit(SD_NR, &(chip->need_reset)); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; chip->card_ready |= SD_CARD; chip->card_fail &= ~SD_CARD; chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw; } else { if (chip->sd_io || (chip->sd_reset_counter >= MAX_RESET_CNT)) { clear_bit(SD_NR, &(chip->need_reset)); chip->sd_reset_counter = 0; chip->sd_show_cnt = 0; } else { chip->sd_reset_counter ++; } chip->card_ready &= ~SD_CARD; chip->card_fail |= SD_CARD; chip->capacity[chip->card2lun[SD_CARD]] = 0; chip->rw_card[chip->card2lun[SD_CARD]] = NULL; rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); if (!chip->ft2_fast_mode) { card_power_off(chip, SD_CARD); } if (chip->sd_io) { chip->sd_int = 0; try_to_switch_sdio_ctrl(chip); } else { disable_card_clock(chip, SD_CARD); } } }
void rtsx_reset_cards(struct rtsx_chip *chip) { if (!chip->need_reset) { return; } rtsx_set_stat(chip, RTSX_STAT_RUN); rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); rtsx_disable_aspm(chip); if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio) { clear_bit(SD_NR, &(chip->need_reset)); } if (chip->need_reset & XD_CARD) { chip->card_exist |= XD_CARD; if (chip->xd_show_cnt >= MAX_SHOW_CNT) { do_reset_xd_card(chip); } else { chip->xd_show_cnt ++; } } if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { if (chip->card_exist & XD_CARD) { clear_bit(SD_NR, &(chip->need_reset)); clear_bit(MS_NR, &(chip->need_reset)); } } if (chip->need_reset & SD_CARD) { chip->card_exist |= SD_CARD; if (chip->sd_show_cnt >= MAX_SHOW_CNT) { rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); do_reset_sd_card(chip); } else { chip->sd_show_cnt ++; } } if (chip->need_reset & MS_CARD) { chip->card_exist |= MS_CARD; if (chip->ms_show_cnt >= MAX_SHOW_CNT) { do_reset_ms_card(chip); } else { chip->ms_show_cnt ++; } } }
void do_reset_ms_card(struct rtsx_chip *chip) { int retval; RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__, chip->ms_reset_counter, chip->card2lun[MS_CARD]); if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) { clear_bit(MS_NR, &(chip->need_reset)); chip->ms_reset_counter = 0; chip->ms_show_cnt = 0; return; } chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; rtsx_set_stat(chip, RTSX_STAT_RUN); rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); retval = reset_ms_card(chip); if (chip->need_release & MS_CARD) return; if (retval == STATUS_SUCCESS) { clear_bit(MS_NR, &(chip->need_reset)); chip->ms_reset_counter = 0; chip->card_ready |= MS_CARD; chip->card_fail &= ~MS_CARD; chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw; } else { if (chip->ms_reset_counter >= MAX_RESET_CNT) { clear_bit(MS_NR, &(chip->need_reset)); chip->ms_reset_counter = 0; chip->ms_show_cnt = 0; } else { chip->ms_reset_counter++; } chip->card_ready &= ~MS_CARD; chip->card_fail |= MS_CARD; chip->capacity[chip->card2lun[MS_CARD]] = 0; chip->rw_card[chip->card2lun[MS_CARD]] = NULL; rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); if (!chip->ft2_fast_mode) card_power_off(chip, MS_CARD); disable_card_clock(chip, MS_CARD); } }
void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip) { rtsx_set_stat(chip, RTSX_STAT_RUN); rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); if (reset_chip) rtsx_reset_chip(chip); chip->int_reg = rtsx_readl(chip, RTSX_BIPR); if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) { release_sdio(chip); release_sd_card(chip); wait_timeout(100); chip->card_exist |= SD_CARD; do_reset_sd_card(chip); } if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) { release_xd_card(chip); wait_timeout(100); chip->card_exist |= XD_CARD; do_reset_xd_card(chip); } if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) { release_ms_card(chip); wait_timeout(100); chip->card_exist |= MS_CARD; do_reset_ms_card(chip); } chip->need_reinit = 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); }
void rtsx_init_cards(struct rtsx_chip *chip) { if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) { RTSX_DEBUGP("Reset chip in polling thread!\n"); rtsx_reset_chip(chip); RTSX_CLR_DELINK(chip); } #ifdef DISABLE_CARD_INT card_cd_debounce(chip, &(chip->need_reset), &(chip->need_release)); #endif if (chip->need_release) { if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { if (chip->int_reg & XD_EXIST) { clear_bit(SD_NR, &(chip->need_release)); clear_bit(MS_NR, &(chip->need_release)); } } if (!(chip->card_exist & SD_CARD) && !chip->sd_io) clear_bit(SD_NR, &(chip->need_release)); if (!(chip->card_exist & XD_CARD)) clear_bit(XD_NR, &(chip->need_release)); if (!(chip->card_exist & MS_CARD)) clear_bit(MS_NR, &(chip->need_release)); RTSX_DEBUGP("chip->need_release = 0x%x\n", (unsigned int)(chip->need_release)); #ifdef SUPPORT_OCP if (chip->need_release) { if (CHECK_PID(chip, 0x5209)) { u8 mask = 0, val = 0; if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) { mask |= MS_OCP_INT_CLR | MS_OC_CLR; val |= MS_OCP_INT_CLR | MS_OC_CLR; } } if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { mask |= SD_OCP_INT_CLR | SD_OC_CLR; val |= SD_OCP_INT_CLR | SD_OC_CLR; } if (mask) rtsx_write_register(chip, OCPCTL, mask, val); } else { if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER)) rtsx_write_register(chip, OCPCLR, CARD_OC_INT_CLR | CARD_OC_CLR, CARD_OC_INT_CLR | CARD_OC_CLR); } chip->ocp_stat = 0; } #endif if (chip->need_release) { rtsx_set_stat(chip, RTSX_STAT_RUN); rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); } if (chip->need_release & SD_CARD) { clear_bit(SD_NR, &(chip->need_release)); chip->card_exist &= ~SD_CARD; chip->card_ejected &= ~SD_CARD; chip->card_fail &= ~SD_CARD; CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]); chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); release_sdio(chip); release_sd_card(chip); } if (chip->need_release & XD_CARD) { clear_bit(XD_NR, &(chip->need_release)); chip->card_exist &= ~XD_CARD; chip->card_ejected &= ~XD_CARD; chip->card_fail &= ~XD_CARD; CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]); chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0; release_xd_card(chip); if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0xC0); } if (chip->need_release & MS_CARD) { clear_bit(MS_NR, &(chip->need_release)); chip->card_exist &= ~MS_CARD; chip->card_ejected &= ~MS_CARD; chip->card_fail &= ~MS_CARD; CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]); chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; release_ms_card(chip); } RTSX_DEBUGP("chip->card_exist = 0x%x\n", chip->card_exist); if (!chip->card_exist) turn_off_led(chip, LED_GPIO); } if (chip->need_reset) { RTSX_DEBUGP("chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset)); rtsx_reset_cards(chip); } if (chip->need_reinit) { RTSX_DEBUGP("chip->need_reinit = 0x%x\n", (unsigned int)(chip->need_reinit)); rtsx_reinit_cards(chip, 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); }