--- zzzz-none-000/linux-5.15.111/drivers/mmc/core/core.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-arm-6670-761/linux-5.15.111/drivers/mmc/core/core.c 2024-02-07 09:27:48.000000000 +0000 @@ -7,6 +7,14 @@ * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. */ + + /****************************************************************** + + Includes Intel Corporation's changes/modifications dated: 05/2012. + Changed/modified portions - Copyright(c) 2012-2017, Intel Corporation. + +******************************************************************/ + #include #include #include @@ -46,6 +54,9 @@ #include "mmc_ops.h" #include "sd_ops.h" #include "sdio_ops.h" +#if defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES) +#include "../host/sdhci.h" +#endif /* The max erase timeout, used when host->max_busy_timeout isn't specified */ #define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */ @@ -194,6 +205,9 @@ pr_debug("%s: %d bytes transferred: %d\n", mmc_hostname(host), mrq->data->bytes_xfered, mrq->data->error); +#ifdef CONFIG_ARCH_GEN3 + trace_mmc_blk_rw_end(cmd->opcode, cmd->arg, mrq->data); +#endif } if (mrq->stop) { @@ -785,6 +799,7 @@ unsigned long flags; int stop; bool pm = false; + bool hw_lock __maybe_unused = false; might_sleep(); @@ -804,13 +819,20 @@ host->claimed = 1; mmc_ctx_set_claimer(host, ctx, task); host->claim_cnt += 1; - if (host->claim_cnt == 1) + if (host->claim_cnt == 1) { + hw_lock = true; pm = true; + } } else wake_up(&host->wq); spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); +#if defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES) + if (hw_lock && + ((host->caps2 & MMC_CAP2_RESCAN_ACTIVE) == 0)) + MMC_LOCK_HW_MUTEX(host); +#endif if (pm) pm_runtime_get_sync(mmc_dev(host)); @@ -840,6 +862,16 @@ host->claimer->task = NULL; host->claimer = NULL; spin_unlock_irqrestore(&host->lock, flags); +#if defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES) + /* + * mmc_release_host is the end point of a set of MMC operations. + * Unlock the HW Mutex when a task doesn't own the controller + */ + if ((host->caps2 & MMC_CAP2_RESCAN_ACTIVE) == 0) + { + MMC_UNLOCK_HW_MUTEX(host); + } +#endif wake_up(&host->wq); pm_runtime_mark_last_busy(mmc_dev(host)); if (host->caps & MMC_CAP_SYNC_RUNTIME_PM) @@ -2241,6 +2273,20 @@ goto out; } +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + host->caps2 |= MMC_CAP2_RESCAN_ACTIVE; /* Prevent Release and re-take HW_Mutex during rescan */ + + if (MMC_HOST_SUPPORTS_HW_MUTEX(host)) + { + // We disabled register writes during initialization and the host is not + // currently initialized. Power up then power cycle the emmc/host to + // ensure it is configured as it believes it is currently off and during + // the cycle, the off is ignored when it shouldn't be. + mmc_power_up(host, host->ocr_avail); + mmc_power_cycle(host, host->ocr_avail); + } +#endif + for (i = 0; i < ARRAY_SIZE(freqs); i++) { unsigned int freq = freqs[i]; if (freq > host->f_max) { @@ -2253,6 +2299,9 @@ if (freqs[i] <= host->f_min) break; } +#if defined(CONFIG_ARCH_GEN3) + host->caps2 &= ~MMC_CAP2_RESCAN_ACTIVE; +#endif mmc_release_host(host); out: @@ -2266,9 +2315,14 @@ host->rescan_disable = 0; if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { +#ifndef CONFIG_ARCH_GEN3 + /* To avoid deadlock */ mmc_claim_host(host); +#endif mmc_power_up(host, host->ocr_avail); +#ifndef CONFIG_ARCH_GEN3 mmc_release_host(host); +#endif } mmc_gpiod_request_cd_irq(host); @@ -2303,9 +2357,14 @@ return; } +#ifndef CONFIG_ARCH_GEN3 + /* To avoid deadlock */ mmc_claim_host(host); +#endif mmc_power_off(host); +#ifndef CONFIG_ARCH_GEN3 mmc_release_host(host); +#endif } static int __init mmc_init(void)