Loading drivers/mmc/core/core.c +3 −2 Original line number Diff line number Diff line Loading @@ -144,8 +144,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) int err = cmd->error; /* Flag re-tuning needed on CRC errors */ if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && if (cmd->opcode != MMC_SEND_TUNING_BLOCK && cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && !host->retune_crc_disable && (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || (mrq->data && mrq->data->error == -EILSEQ) || (mrq->stop && mrq->stop->error == -EILSEQ))) Loading drivers/mmc/core/sdio_io.c +77 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include "sdio_ops.h" #include "core.h" #include "card.h" #include "host.h" /** * sdio_claim_host - exclusively claim a bus for a certain SDIO function Loading Loading @@ -734,3 +735,79 @@ int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags) return 0; } EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags); /** * sdio_retune_crc_disable - temporarily disable retuning on CRC errors * @func: SDIO function attached to host * * If the SDIO card is known to be in a state where it might produce * CRC errors on the bus in response to commands (like if we know it is * transitioning between power states), an SDIO function driver can * call this function to temporarily disable the SD/MMC core behavior of * triggering an automatic retuning. * * This function should be called while the host is claimed and the host * should remain claimed until sdio_retune_crc_enable() is called. * Specifically, the expected sequence of calls is: * - sdio_claim_host() * - sdio_retune_crc_disable() * - some number of calls like sdio_writeb() and sdio_readb() * - sdio_retune_crc_enable() * - sdio_release_host() */ void sdio_retune_crc_disable(struct sdio_func *func) { func->card->host->retune_crc_disable = true; } EXPORT_SYMBOL_GPL(sdio_retune_crc_disable); /** * sdio_retune_crc_enable - re-enable retuning on CRC errors * @func: SDIO function attached to host * * This is the compement to sdio_retune_crc_disable(). */ void sdio_retune_crc_enable(struct sdio_func *func) { func->card->host->retune_crc_disable = false; } EXPORT_SYMBOL_GPL(sdio_retune_crc_enable); /** * sdio_retune_hold_now - start deferring retuning requests till release * @func: SDIO function attached to host * * This function can be called if it's currently a bad time to do * a retune of the SDIO card. Retune requests made during this time * will be held and we'll actually do the retune sometime after the * release. * * This function could be useful if an SDIO card is in a power state * where it can respond to a small subset of commands that doesn't * include the retuning command. Care should be taken when using * this function since (presumably) the retuning request we might be * deferring was made for a good reason. * * This function should be called while the host is claimed. */ void sdio_retune_hold_now(struct sdio_func *func) { mmc_retune_hold_now(func->card->host); } EXPORT_SYMBOL_GPL(sdio_retune_hold_now); /** * sdio_retune_release - signal that it's OK to retune now * @func: SDIO function attached to host * * This is the complement to sdio_retune_hold_now(). Calling this * function won't make a retune happen right away but will allow * them to be scheduled normally. * * This function should be called while the host is claimed. */ void sdio_retune_release(struct sdio_func *func) { mmc_retune_release(func->card->host); } EXPORT_SYMBOL_GPL(sdio_retune_release); drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +12 −5 Original line number Diff line number Diff line Loading @@ -678,6 +678,12 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) brcmf_dbg(TRACE, "Enter: on=%d\n", on); sdio_retune_crc_disable(bus->sdiodev->func1); /* Cannot re-tune if device is asleep; defer till we're awake */ if (on) sdio_retune_hold_now(bus->sdiodev->func1); wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); /* 1st KSO write goes to AOS wake up core if device is asleep */ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); Loading Loading @@ -738,6 +744,11 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) if (try_cnt > MAX_KSO_ATTEMPTS) brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err); if (on) sdio_retune_release(bus->sdiodev->func1); sdio_retune_crc_enable(bus->sdiodev->func1); return err; } Loading Loading @@ -3375,11 +3386,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus) { if (bus->ci->chip == CY_CC_43012_CHIP_ID || bus->ci->chip == CY_CC_4373_CHIP_ID || bus->ci->chip == BRCM_CC_4339_CHIP_ID || bus->ci->chip == BRCM_CC_4345_CHIP_ID || bus->ci->chip == BRCM_CC_4354_CHIP_ID) if (bus->ci->chip == CY_CC_43012_CHIP_ID) return true; else return false; Loading include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -398,6 +398,7 @@ struct mmc_host { unsigned int retune_now:1; /* do re-tuning at next req */ unsigned int retune_paused:1; /* re-tuning is temporarily disabled */ unsigned int use_blk_mq:1; /* use blk-mq */ unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ Loading include/linux/mmc/sdio_func.h +6 −0 Original line number Diff line number Diff line Loading @@ -167,4 +167,10 @@ extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b, extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func); extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags); extern void sdio_retune_crc_disable(struct sdio_func *func); extern void sdio_retune_crc_enable(struct sdio_func *func); extern void sdio_retune_hold_now(struct sdio_func *func); extern void sdio_retune_release(struct sdio_func *func); #endif /* LINUX_MMC_SDIO_FUNC_H */ Loading
drivers/mmc/core/core.c +3 −2 Original line number Diff line number Diff line Loading @@ -144,8 +144,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) int err = cmd->error; /* Flag re-tuning needed on CRC errors */ if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && if (cmd->opcode != MMC_SEND_TUNING_BLOCK && cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && !host->retune_crc_disable && (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || (mrq->data && mrq->data->error == -EILSEQ) || (mrq->stop && mrq->stop->error == -EILSEQ))) Loading
drivers/mmc/core/sdio_io.c +77 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include "sdio_ops.h" #include "core.h" #include "card.h" #include "host.h" /** * sdio_claim_host - exclusively claim a bus for a certain SDIO function Loading Loading @@ -734,3 +735,79 @@ int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags) return 0; } EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags); /** * sdio_retune_crc_disable - temporarily disable retuning on CRC errors * @func: SDIO function attached to host * * If the SDIO card is known to be in a state where it might produce * CRC errors on the bus in response to commands (like if we know it is * transitioning between power states), an SDIO function driver can * call this function to temporarily disable the SD/MMC core behavior of * triggering an automatic retuning. * * This function should be called while the host is claimed and the host * should remain claimed until sdio_retune_crc_enable() is called. * Specifically, the expected sequence of calls is: * - sdio_claim_host() * - sdio_retune_crc_disable() * - some number of calls like sdio_writeb() and sdio_readb() * - sdio_retune_crc_enable() * - sdio_release_host() */ void sdio_retune_crc_disable(struct sdio_func *func) { func->card->host->retune_crc_disable = true; } EXPORT_SYMBOL_GPL(sdio_retune_crc_disable); /** * sdio_retune_crc_enable - re-enable retuning on CRC errors * @func: SDIO function attached to host * * This is the compement to sdio_retune_crc_disable(). */ void sdio_retune_crc_enable(struct sdio_func *func) { func->card->host->retune_crc_disable = false; } EXPORT_SYMBOL_GPL(sdio_retune_crc_enable); /** * sdio_retune_hold_now - start deferring retuning requests till release * @func: SDIO function attached to host * * This function can be called if it's currently a bad time to do * a retune of the SDIO card. Retune requests made during this time * will be held and we'll actually do the retune sometime after the * release. * * This function could be useful if an SDIO card is in a power state * where it can respond to a small subset of commands that doesn't * include the retuning command. Care should be taken when using * this function since (presumably) the retuning request we might be * deferring was made for a good reason. * * This function should be called while the host is claimed. */ void sdio_retune_hold_now(struct sdio_func *func) { mmc_retune_hold_now(func->card->host); } EXPORT_SYMBOL_GPL(sdio_retune_hold_now); /** * sdio_retune_release - signal that it's OK to retune now * @func: SDIO function attached to host * * This is the complement to sdio_retune_hold_now(). Calling this * function won't make a retune happen right away but will allow * them to be scheduled normally. * * This function should be called while the host is claimed. */ void sdio_retune_release(struct sdio_func *func) { mmc_retune_release(func->card->host); } EXPORT_SYMBOL_GPL(sdio_retune_release);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +12 −5 Original line number Diff line number Diff line Loading @@ -678,6 +678,12 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) brcmf_dbg(TRACE, "Enter: on=%d\n", on); sdio_retune_crc_disable(bus->sdiodev->func1); /* Cannot re-tune if device is asleep; defer till we're awake */ if (on) sdio_retune_hold_now(bus->sdiodev->func1); wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); /* 1st KSO write goes to AOS wake up core if device is asleep */ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); Loading Loading @@ -738,6 +744,11 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) if (try_cnt > MAX_KSO_ATTEMPTS) brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err); if (on) sdio_retune_release(bus->sdiodev->func1); sdio_retune_crc_enable(bus->sdiodev->func1); return err; } Loading Loading @@ -3375,11 +3386,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus) { if (bus->ci->chip == CY_CC_43012_CHIP_ID || bus->ci->chip == CY_CC_4373_CHIP_ID || bus->ci->chip == BRCM_CC_4339_CHIP_ID || bus->ci->chip == BRCM_CC_4345_CHIP_ID || bus->ci->chip == BRCM_CC_4354_CHIP_ID) if (bus->ci->chip == CY_CC_43012_CHIP_ID) return true; else return false; Loading
include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -398,6 +398,7 @@ struct mmc_host { unsigned int retune_now:1; /* do re-tuning at next req */ unsigned int retune_paused:1; /* re-tuning is temporarily disabled */ unsigned int use_blk_mq:1; /* use blk-mq */ unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ Loading
include/linux/mmc/sdio_func.h +6 −0 Original line number Diff line number Diff line Loading @@ -167,4 +167,10 @@ extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b, extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func); extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags); extern void sdio_retune_crc_disable(struct sdio_func *func); extern void sdio_retune_crc_enable(struct sdio_func *func); extern void sdio_retune_hold_now(struct sdio_func *func); extern void sdio_retune_release(struct sdio_func *func); #endif /* LINUX_MMC_SDIO_FUNC_H */