Re: [PATCH v2 0/3] Add RPMPD support for MSM8974

2024-02-13 Thread Ulf Hansson
On Sat, 10 Feb 2024 at 17:39, Luca Weiss  wrote:
>
> Add driver support for the RPM power domains found on the different
> MSM8974 devices.
>
> Devicetree integration will come at a later point since also some
> mostly remoteproc drivers need to be adjusted.
>
> Also the MX power domains on this SoC seems to work quite a bit
> differently, we'd need to send raw voltages to it, so these are ignored
> in this series.
>
> Signed-off-by: Luca Weiss 

Applied for next, thanks!

Note that patch1 is also available at the immutable dt branch, if soc
maintainers need to pull it in too.

Kind regards
Uffe


> ---
> Changes in v2:
> - Drop MSM8974_VDDGFX_AO in all patches
> - Link to v1: 
> https://lore.kernel.org/r/20240210-msm8974-rpmpd-v1-0-de9355e68...@z3ntu.xyz
>
> ---
> Luca Weiss (3):
>   dt-bindings: power: rpmpd: Add MSM8974 power domains
>   pmdomain: qcom: rpmpd: Add MSM8974+PM8841 power domains
>   pmdomain: qcom: rpmpd: Add MSM8974PRO+PMA8084 power domains
>
>  .../devicetree/bindings/power/qcom,rpmpd.yaml  |  2 +
>  drivers/pmdomain/qcom/rpmpd.c  | 83 
> ++
>  include/dt-bindings/power/qcom-rpmpd.h |  7 ++
>  3 files changed, 92 insertions(+)
> ---
> base-commit: 6e3fa474051f3d276ea708bdb8e8e1f66d1d3ee5
> change-id: 20240210-msm8974-rpmpd-6e48fe374275
>
> Best regards,
> --
> Luca Weiss 
>



Re: [PATCH v3 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2024-02-07 Thread Ulf Hansson
On Tue, 30 Jan 2024 at 13:39, Ulf Hansson  wrote:
>
> Rafael, my plan is queue up this series via my pmdomain tree. Please let me 
> know
> if you see any issues with that, especially around patch1.
>
> Updates in v3:
> - Added tested-by, reviewed-by and suggested-by tags. No other changes
> have been made.
>
> Updates in v2:
> - Ccing Daniel Baluta and Iuliana Prodan the NXP remoteproc patches to
> requests help with testing.
> - Fixed NULL pointer bug in patch1, pointed out by Nikunj.
> - Added some tested/reviewed-by tags.
>
> Attaching/detaching of a device to multiple PM domains has started to become a
> common operation for many drivers, typically during ->probe() and ->remove().
> In most cases, this has lead to lots of boilerplate code in the drivers.
>
> This series adds a pair of helper functions to manage the attach/detach of a
> device to its multiple PM domains. Moreover, a couple of drivers have been
> converted to use the new helpers as a proof of concept.
>
> Note 1)
> The changes in the drivers have only been compile tested, while the helpers
> have been tested along with a couple of local dummy drivers that I have hacked
> up to model both genpd providers and genpd consumers.
>
> Note 2)
> I was struggling to make up mind if we should have a separate helper to attach
> all available power-domains described in DT, rather than providing "NULL" to 
> the
> dev_pm_domain_attach_list(). I decided not to, but please let me know if you
> prefer the other option.
>
> Note 3)
> For OPP integration, as a follow up I am striving to make the
> dev_pm_opp_attach_genpd() redundant. Instead I think we should move towards
> using dev_pm_opp_set_config()->_opp_set_required_devs(), which would allow us 
> to
> use the helpers that $subject series is adding.
>
> Kind regards
> Ulf Hansson
>
> Ulf Hansson (5):
>   PM: domains: Add helper functions to attach/detach multiple PM domains
>   remoteproc: imx_dsp_rproc: Convert to
> dev_pm_domain_attach|detach_list()
>   remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
>   remoteproc: qcom_q6v5_adsp: Convert to
> dev_pm_domain_attach|detach_list()
>   media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec
>
>  drivers/base/power/common.c   | 134 +++
>  drivers/media/platform/qcom/venus/core.c  |  12 +-
>  drivers/media/platform/qcom/venus/core.h  |   7 +-
>  .../media/platform/qcom/venus/pm_helpers.c|  48 ++
>  drivers/remoteproc/imx_dsp_rproc.c|  82 +
>  drivers/remoteproc/imx_rproc.c|  73 +---
>  drivers/remoteproc/qcom_q6v5_adsp.c   | 160 --
>  include/linux/pm_domain.h |  38 +
>  8 files changed, 289 insertions(+), 265 deletions(-)
>
>

I have now applied this to my next branch to my pmdomain tree, to get
it more tested in linux-next.

Please let me know if there are objections to this or if any of you
want to provide an ack/tested/reviewed-by tag, thanks!

Kind regards
Uffe



[PATCH v3 5/5] media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

2024-01-30 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the vcodec PM domains,
by converting into using dev_pm_domain_attach|detach_list().

Cc: Mauro Carvalho Chehab 
Cc: Stanimir Varbanov 
Cc: Vikash Garodia 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Tested-by: Bryan O'Donoghue 
Reviewed-by: Bryan O'Donoghue 
Signed-off-by: Ulf Hansson 
---

Changes in v3:
- None.

Changes in v2:
- Added reviewed-by and tested-by tags.

---
 drivers/media/platform/qcom/venus/core.c  | 12 +++--
 drivers/media/platform/qcom/venus/core.h  |  7 ++-
 .../media/platform/qcom/venus/pm_helpers.c| 48 +++
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c 
b/drivers/media/platform/qcom/venus/core.c
index a712dd4f02a5..ce206b709754 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -114,7 +115,8 @@ static void venus_sys_error_handler(struct work_struct 
*work)
pm_runtime_put_sync(core->dev);
 
for (i = 0; i < max_attempts; i++) {
-   if (!core->pmdomains[0] || 
!pm_runtime_active(core->pmdomains[0]))
+   if (!core->pmdomains ||
+   !pm_runtime_active(core->pmdomains->pd_devs[0]))
break;
usleep_range(1000, 1500);
}
@@ -705,7 +707,7 @@ static const struct venus_resources sdm845_res_v2 = {
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec1_clks = { "vcodec1_core", "vcodec1_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
.vcodec_pmdomains_num = 3,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 2,
@@ -754,7 +756,7 @@ static const struct venus_resources sc7180_res = {
.clks_num = 3,
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
@@ -811,7 +813,7 @@ static const struct venus_resources sm8250_res = {
.resets_num = 2,
.vcodec0_clks = { "vcodec0_core" },
.vcodec_clks_num = 1,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "mx", NULL },
.vcodec_num = 1,
@@ -870,7 +872,7 @@ static const struct venus_resources sc7280_res = {
.clks_num = 3,
.vcodec0_clks = {"vcodec_core", "vcodec_bus"},
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 4a633261ece4..7ef341bf21cc 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -25,7 +25,6 @@
 
 #define VIDC_CLKS_NUM_MAX  4
 #define VIDC_VCODEC_CLKS_NUM_MAX   2
-#define VIDC_PMDOMAINS_NUM_MAX 3
 #define VIDC_RESETS_NUM_MAX2
 
 extern int venus_fw_debug;
@@ -72,7 +71,7 @@ struct venus_resources {
const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX];
const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
unsigned int vcodec_clks_num;
-   const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
+   const char **vcodec_pmdomains;
unsigned int vcodec_pmdomains_num;
const char **opp_pmdomain;
unsigned int vcodec_num;
@@ -134,7 +133,7 @@ struct venus_format {
  * @video_path: an interconnect handle to video to/from memory path
  * @cpucfg_path: an interconnect handle to cpu configuration path
  * @has_opp_table: does OPP table exist
- * @pmdomains: an array of pmdomains struct device pointers
+ * @pmdomains: a pointer to a list of pmdomains
  * @opp_dl_venus: an device-link for device OPP
  * @opp_pmdomain: an OPP power-domain
  * @resets: an array of reset signals
@@ -187,7 +186,7 @@ struct venus_core {
struct icc_path *video_path;
struct icc_path *cpucfg_path;
bool has_opp_tab

[PATCH v3 4/5] remoteproc: qcom_q6v5_adsp: Convert to dev_pm_domain_attach|detach_list()

2024-01-30 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the various PM domain
cases, by converting into using dev_pm_domain_attach|detach_list().

As a part of the conversion, we are moving over to use device_links, which
simplifies the runtime PM support too. Moreover, while attaching let's
trust that an already attached single PM domain is the correct one.

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Signed-off-by: Ulf Hansson 
---

Changes in v3:
- None.

Changes in v2:
- None.

---
 drivers/remoteproc/qcom_q6v5_adsp.c | 160 +---
 1 file changed, 73 insertions(+), 87 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c 
b/drivers/remoteproc/qcom_q6v5_adsp.c
index 6c67514cc493..93f9a1537ec6 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -55,8 +55,6 @@
 #define QDSP6SS_CORE_CBCR  0x20
 #define QDSP6SS_SLEEP_CBCR 0x3c
 
-#define QCOM_Q6V5_RPROC_PROXY_PD_MAX   3
-
 #define LPASS_BOOT_CORE_START  BIT(0)
 #define LPASS_BOOT_CMD_START   BIT(0)
 #define LPASS_EFUSE_Q6SS_EVB_SEL 0x0
@@ -74,7 +72,8 @@ struct adsp_pil_data {
 
const char **clk_ids;
int num_clks;
-   const char **proxy_pd_names;
+   const char **pd_names;
+   unsigned int num_pds;
const char *load_state;
 };
 
@@ -110,8 +109,7 @@ struct qcom_adsp {
size_t mem_size;
bool has_iommu;
 
-   struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
-   size_t proxy_pd_count;
+   struct dev_pm_domain_list *pd_list;
 
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_ssr ssr_subdev;
@@ -120,98 +118,92 @@ struct qcom_adsp {
int (*shutdown)(struct qcom_adsp *adsp);
 };
 
-static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
-const char **pd_names)
+static int qcom_rproc_pds_attach(struct qcom_adsp *adsp, const char **pd_names,
+unsigned int num_pds)
 {
-   struct device **devs = adsp->proxy_pds;
-   size_t num_pds = 0;
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_names = pd_names,
+   .num_pd_names = num_pds,
+   };
int ret;
-   int i;
-
-   if (!pd_names)
-   return 0;
 
/* Handle single power domain */
-   if (dev->pm_domain) {
-   devs[0] = dev;
-   pm_runtime_enable(dev);
-   return 1;
-   }
+   if (dev->pm_domain)
+   goto out;
 
-   while (pd_names[num_pds])
-   num_pds++;
+   if (!pd_names)
+   return 0;
 
-   if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
-   return -E2BIG;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   if (ret < 0)
+   return ret;
 
-   for (i = 0; i < num_pds; i++) {
-   devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
-   if (IS_ERR_OR_NULL(devs[i])) {
-   ret = PTR_ERR(devs[i]) ? : -ENODATA;
-   goto unroll_attach;
-   }
-   }
+out:
+   pm_runtime_enable(dev);
+   return 0;
+}
 
-   return num_pds;
+static void qcom_rproc_pds_detach(struct qcom_adsp *adsp)
+{
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
 
-unroll_attach:
-   for (i--; i >= 0; i--)
-   dev_pm_domain_detach(devs[i], false);
+   dev_pm_domain_detach_list(pds);
 
-   return ret;
+   if (dev->pm_domain || pds)
+   pm_runtime_disable(adsp->dev);
 }
 
-static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
- size_t pd_count)
+static int qcom_rproc_pds_enable(struct qcom_adsp *adsp)
 {
struct device *dev = adsp->dev;
-   int i;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
+   int ret, i = 0;
 
-   /* Handle single power domain */
-   if (dev->pm_domain && pd_count) {
-   pm_runtime_disable(dev);
-   return;
-   }
+   if (!dev->pm_domain && !pds)
+   return 0;
 
-   for (i = 0; i < pd_count; i++)
-   dev_pm_domain_detach(pds[i], false);
-}
+   if (dev->pm_domain)
+   dev_pm_genpd_set_performance_state(dev, INT_MAX);
 
-static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
-size_t pd_count)
-{
-   int ret;
-   int i;
-
-   for (i = 0; i < pd_count; i++) {
-   dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
-   ret = pm_runtime_resume_and_get(pds[i]);
-   if (ret < 0) {
-   dev_pm_genpd_set_performance_state(pds[i], 0);
-   

[PATCH v3 3/5] remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-30 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: Daniel Baluta 
Cc: 
Tested-by: Iuliana Prodan 
Reviewed-by: Iuliana Prodan 
Reviewed-by: Mathieu Poirier 
Signed-off-by: Ulf Hansson 
---

Changes in v3:
- Added reviewed-by and tested-by tags.

Changes in v2:
- None.

---
 drivers/remoteproc/imx_rproc.c | 73 +-
 1 file changed, 9 insertions(+), 64 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 8bb293b9f327..3161f14442bc 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -92,7 +92,6 @@ struct imx_rproc_mem {
 
 static int imx_rproc_xtr_mbox_init(struct rproc *rproc);
 static void imx_rproc_free_mbox(struct rproc *rproc);
-static int imx_rproc_detach_pd(struct rproc *rproc);
 
 struct imx_rproc {
struct device   *dev;
@@ -113,10 +112,8 @@ struct imx_rproc {
u32 rproc_pt;   /* partition id */
u32 rsrc_id;/* resource id */
u32 entry;  /* cpu start address */
-   int num_pd;
u32 core_index;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
 };
 
 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
@@ -853,7 +850,7 @@ static void imx_rproc_put_scu(struct rproc *rproc)
return;
 
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
-   imx_rproc_detach_pd(rproc);
+   dev_pm_domain_detach_list(priv->pd_list);
return;
}
 
@@ -880,72 +877,20 @@ static int imx_rproc_partition_notify(struct 
notifier_block *nb,
 static int imx_rproc_attach_pd(struct imx_rproc *priv)
 {
struct device *dev = priv->dev;
-   int ret, i;
-
-   /*
-* If there is only one power-domain entry, the platform driver 
framework
-* will handle it, no need handle it in this driver.
-*/
-   priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains",
- "#power-domain-cells");
-   if (priv->num_pd <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev), GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_pd; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pd;
-   }
-
-   priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], 
DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME | 
DL_FLAG_RPM_ACTIVE);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pd;
-   }
-   }
-
-   return 0;
-
-detach_pd:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_rproc_detach_pd(struct rproc *rproc)
-{
-   struct imx_rproc *priv = rproc->priv;
-   int i;
+   int ret;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_flags = PD_FLAG_DEV_LINK_ON,
+   };
 
/*
 * If there is only one power-domain entry, the platform driver 
framework
 * will handle it, no need handle it in this driver.
 */
-   if (priv->num_pd <= 1)
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_pd; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   return ret < 0 ? ret : 0;
 }
 
 static int imx_rproc_detect_mode(struct imx_rproc *priv)
-- 
2.34.1




[PATCH v3 2/5] remoteproc: imx_dsp_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-30 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: Daniel Baluta 
Cc: 
Tested-by: Iuliana Prodan 
Reviewed-by: Iuliana Prodan 
Reviewed-by: Mathieu Poirier 
Signed-off-by: Ulf Hansson 
---

Changes in v3:
- Added reviewed-by and tested-by tags.

Changes in v2:
- None.

---
 drivers/remoteproc/imx_dsp_rproc.c | 82 --
 1 file changed, 9 insertions(+), 73 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c 
b/drivers/remoteproc/imx_dsp_rproc.c
index a1c62d15f16c..d73727a5828a 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -103,12 +103,10 @@ enum imx_dsp_rp_mbox_messages {
  * @tx_ch: mailbox tx channel handle
  * @rx_ch: mailbox rx channel handle
  * @rxdb_ch: mailbox rx doorbell channel handle
- * @pd_dev: power domain device
- * @pd_dev_link: power domain device link
+ * @pd_list: power domain list
  * @ipc_handle: System Control Unit ipc handle
  * @rproc_work: work for processing virtio interrupts
  * @pm_comp: completion primitive to sync for suspend response
- * @num_domains: power domain number
  * @flags: control flags
  */
 struct imx_dsp_rproc {
@@ -121,12 +119,10 @@ struct imx_dsp_rproc {
struct mbox_chan*tx_ch;
struct mbox_chan*rx_ch;
struct mbox_chan*rxdb_ch;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
struct imx_sc_ipc   *ipc_handle;
struct work_struct  rproc_work;
struct completion   pm_comp;
-   int num_domains;
u32 flags;
 };
 
@@ -955,74 +951,14 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
 static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv)
 {
struct device *dev = priv->rproc->dev.parent;
-   int ret, i;
-
-   priv->num_domains = of_count_phandle_with_args(dev->of_node,
-  "power-domains",
-  "#power-domain-cells");
-
-   /* If only one domain, then no need to link the device */
-   if (priv->num_domains <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_domains,
- sizeof(*priv->pd_dev),
- GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_domains,
-  sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_domains; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pm;
-   }
-
-   /*
-* device_link_add will check priv->pd_dev[i], if it is
-* NULL, then will break.
-*/
-   priv->pd_dev_link[i] = device_link_add(dev,
-  priv->pd_dev[i],
-  DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pm;
-   }
-   }
-
-   return 0;
-
-detach_pm:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_dsp_detach_pm_domains(struct imx_dsp_rproc *priv)
-{
-   int i;
+   int ret;
 
-   if (priv->num_domains <= 1)
+   /* A single PM domain is already attached. */
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_domains; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, NULL, >pd_list);
+   return ret < 0 ? ret : 0;
 }
 
 /**
@@ -1154,7 +1090,7 @@ static int im

[PATCH v3 1/5] PM: domains: Add helper functions to attach/detach multiple PM domains

2024-01-30 Thread Ulf Hansson
Attaching/detaching of a device to multiple PM domains has started to
become a common operation for many drivers, typically during ->probe() and
->remove(). In most cases, this has lead to lots of boilerplate code in the
drivers.

To fixup up the situation, let's introduce a pair of helper functions,
dev_pm_domain_attach|detach_list(), that driver can use instead of the
open-coding. Note that, it seems reasonable to limit the support for these
helpers to DT based platforms, at it's the only valid use case for now.

Suggested-by: Daniel Baluta 
Tested-by: Bryan O'Donoghue 
Tested-by: Iuliana Prodan 
Signed-off-by: Ulf Hansson 
---

Changes in v3:
- Added suggested-by and tested-by tags.

Changes in v2:
- Fix NULL pointer bug pointed out by Nikunj.

---
 drivers/base/power/common.c | 134 
 include/linux/pm_domain.h   |  38 ++
 2 files changed, 172 insertions(+)

diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 44ec20918a4d..327d168dd37a 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -167,6 +167,115 @@ struct device *dev_pm_domain_attach_by_name(struct device 
*dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
 
+/**
+ * dev_pm_domain_attach_list - Associate a device with its PM domains.
+ * @dev: The device used to lookup the PM domains for.
+ * @data: The data used for attaching to the PM domains.
+ * @list: An out-parameter with an allocated list of attached PM domains.
+ *
+ * This function helps to attach a device to its multiple PM domains. The
+ * caller, which is typically a driver's probe function, may provide a list of
+ * names for the PM domains that we should try to attach the device to, but it
+ * may also provide an empty list, in case the attach should be done for all of
+ * the available PM domains.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the number of attached PM domains or a negative error code in case 
of
+ * a failure. Note that, to detach the list of PM domains, the driver shall 
call
+ * dev_pm_domain_detach_list(), typically during the remove phase.
+ */
+int dev_pm_domain_attach_list(struct device *dev,
+ const struct dev_pm_domain_attach_data *data,
+ struct dev_pm_domain_list **list)
+{
+   struct device_node *np = dev->of_node;
+   struct dev_pm_domain_list *pds;
+   struct device *pd_dev = NULL;
+   int ret, i, num_pds = 0;
+   bool by_id = true;
+   u32 pd_flags = data ? data->pd_flags : 0;
+   u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
+   DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
+
+   if (dev->pm_domain)
+   return -EEXIST;
+
+   /* For now this is limited to OF based platforms. */
+   if (!np)
+   return 0;
+
+   if (data && data->pd_names) {
+   num_pds = data->num_pd_names;
+   by_id = false;
+   } else {
+   num_pds = of_count_phandle_with_args(np, "power-domains",
+"#power-domain-cells");
+   }
+
+   if (num_pds <= 0)
+   return 0;
+
+   pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
+   if (!pds)
+   return -ENOMEM;
+
+   pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
+   GFP_KERNEL);
+   if (!pds->pd_devs)
+   return -ENOMEM;
+
+   pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
+GFP_KERNEL);
+   if (!pds->pd_links)
+   return -ENOMEM;
+
+   if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
+   link_flags |= DL_FLAG_RPM_ACTIVE;
+
+   for (i = 0; i < num_pds; i++) {
+   if (by_id)
+   pd_dev = dev_pm_domain_attach_by_id(dev, i);
+   else
+   pd_dev = dev_pm_domain_attach_by_name(dev,
+   data->pd_names[i]);
+   if (IS_ERR_OR_NULL(pd_dev)) {
+   ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
+   goto err_attach;
+   }
+
+   if (link_flags) {
+   struct device_link *link;
+
+   link = device_link_add(dev, pd_dev, link_flags);
+   if (!link) {
+   ret = -ENODEV;
+   goto err_link;
+   }
+
+   pds->pd_links[i] = link;
+   }
+
+   pds->pd_devs[i] = pd_dev;
+   }
+
+   pds->num_pds = num_pds;
+   *list = pds;
+   return num_pds;
+
+err_link:
+ 

[PATCH v3 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2024-01-30 Thread Ulf Hansson
Rafael, my plan is queue up this series via my pmdomain tree. Please let me know
if you see any issues with that, especially around patch1. 

Updates in v3:
- Added tested-by, reviewed-by and suggested-by tags. No other changes
have been made.

Updates in v2:
- Ccing Daniel Baluta and Iuliana Prodan the NXP remoteproc patches to
requests help with testing.
- Fixed NULL pointer bug in patch1, pointed out by Nikunj.
- Added some tested/reviewed-by tags.

Attaching/detaching of a device to multiple PM domains has started to become a
common operation for many drivers, typically during ->probe() and ->remove().
In most cases, this has lead to lots of boilerplate code in the drivers.

This series adds a pair of helper functions to manage the attach/detach of a
device to its multiple PM domains. Moreover, a couple of drivers have been
converted to use the new helpers as a proof of concept.

Note 1)
The changes in the drivers have only been compile tested, while the helpers
have been tested along with a couple of local dummy drivers that I have hacked
up to model both genpd providers and genpd consumers.

Note 2)
I was struggling to make up mind if we should have a separate helper to attach
all available power-domains described in DT, rather than providing "NULL" to the
dev_pm_domain_attach_list(). I decided not to, but please let me know if you
prefer the other option.

Note 3)
For OPP integration, as a follow up I am striving to make the
dev_pm_opp_attach_genpd() redundant. Instead I think we should move towards
using dev_pm_opp_set_config()->_opp_set_required_devs(), which would allow us to
use the helpers that $subject series is adding.

Kind regards
Ulf Hansson

Ulf Hansson (5):
  PM: domains: Add helper functions to attach/detach multiple PM domains
  remoteproc: imx_dsp_rproc: Convert to
dev_pm_domain_attach|detach_list()
  remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
  remoteproc: qcom_q6v5_adsp: Convert to
dev_pm_domain_attach|detach_list()
  media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

 drivers/base/power/common.c   | 134 +++
 drivers/media/platform/qcom/venus/core.c  |  12 +-
 drivers/media/platform/qcom/venus/core.h  |   7 +-
 .../media/platform/qcom/venus/pm_helpers.c|  48 ++
 drivers/remoteproc/imx_dsp_rproc.c|  82 +
 drivers/remoteproc/imx_rproc.c|  73 +---
 drivers/remoteproc/qcom_q6v5_adsp.c   | 160 --
 include/linux/pm_domain.h |  38 +
 8 files changed, 289 insertions(+), 265 deletions(-)

-- 
2.34.1




Re: [PATCH v2 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2024-01-26 Thread Ulf Hansson
On Fri, 5 Jan 2024 at 17:01, Ulf Hansson  wrote:
>
> Updates in v2:
> - Ccing Daniel Baluta and Iuliana Prodan the NXP remoteproc patches to
> requests help with testing.
> - Fixed NULL pointer bug in patch1, pointed out by Nikunj.
> - Added some tested/reviewed-by tags.
>
>
> Attaching/detaching of a device to multiple PM domains has started to become a
> common operation for many drivers, typically during ->probe() and ->remove().
> In most cases, this has lead to lots of boilerplate code in the drivers.
>
> This series adds a pair of helper functions to manage the attach/detach of a
> device to its multiple PM domains. Moreover, a couple of drivers have been
> converted to use the new helpers as a proof of concept.
>
> Note 1)
> The changes in the drivers have only been compile tested, while the helpers
> have been tested along with a couple of local dummy drivers that I have hacked
> up to model both genpd providers and genpd consumers.
>
> Note 2)
> I was struggling to make up mind if we should have a separate helper to attach
> all available power-domains described in DT, rather than providing "NULL" to 
> the
> dev_pm_domain_attach_list(). I decided not to, but please let me know if you
> prefer the other option.
>
> Note 3)
> For OPP integration, as a follow up I am striving to make the
> dev_pm_opp_attach_genpd() redundant. Instead I think we should move towards
> using dev_pm_opp_set_config()->_opp_set_required_devs(), which would allow us 
> to
> use the helpers that $subject series is adding.
>
> Kind regards
> Ulf Hansson

Rafael, Greg, do have any objections to this series or would you be
okay that I queue this up via my pmdomain tree?

Kind regards
Uffe

>
>
> Ulf Hansson (5):
>   PM: domains: Add helper functions to attach/detach multiple PM domains
>   remoteproc: imx_dsp_rproc: Convert to
> dev_pm_domain_attach|detach_list()
>   remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
>   remoteproc: qcom_q6v5_adsp: Convert to
> dev_pm_domain_attach|detach_list()
>   media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec
>
>  drivers/base/power/common.c   | 134 +++
>  drivers/media/platform/qcom/venus/core.c  |  12 +-
>  drivers/media/platform/qcom/venus/core.h  |   7 +-
>  .../media/platform/qcom/venus/pm_helpers.c|  48 ++
>  drivers/remoteproc/imx_dsp_rproc.c|  82 +
>  drivers/remoteproc/imx_rproc.c|  73 +---
>  drivers/remoteproc/qcom_q6v5_adsp.c   | 160 --
>  include/linux/pm_domain.h |  38 +
>  8 files changed, 289 insertions(+), 265 deletions(-)
>
> --
> 2.34.1



Re: [PATCH v2 3/5] remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-23 Thread Ulf Hansson
On Tue, 23 Jan 2024 at 02:27, Mathieu Poirier
 wrote:
>
> On Mon, Jan 22, 2024 at 01:02:08PM -0700, Mathieu Poirier wrote:
> > On Mon, 22 Jan 2024 at 10:51, Iuliana Prodan  wrote:
> > >
> > > On 1/5/2024 6:01 PM, Ulf Hansson wrote:
> > > > Let's avoid the boilerplate code to manage the multiple PM domain case, 
> > > > by
> > > > converting into using dev_pm_domain_attach|detach_list().
> > > >
> > > > Cc: Mathieu Poirier 
> > > > Cc: Bjorn Andersson 
> > > > Cc: Shawn Guo 
> > > > Cc: Sascha Hauer 
> > > > Cc: Iuliana Prodan 
> > > > Cc: Daniel Baluta 
> > > > Cc: 
> > > > Signed-off-by: Ulf Hansson 
> > > > ---
> > > >
> > > > Changes in v2:
> > > >   - None.
> > > >
> > > > Iuliana/Daniel I am ccing you to request help with test/review of this 
> > > > change.
> > > > Note that, you will need patch 1/5 in the series too, to be able to 
> > > > test this.
> > > >
> > > > Kind regards
> > > > Ulf Hansson
> > >
> > > Tested-by: Iuliana Prodan 
> > > Reviewed-by: Iuliana Prodan 
> > >
> >
> > Thanks for the leg-work on this.  I'll pick this up in rc1 later this week.
>
> Looking at the other files in this set, Ulf of perhaps Bjorn should take this
> set.

Yes, all patches in the series depend on the new helper function that
is introduced in patch 1.

I can certainly take the whole series via my pmdomain tree, if that's
fine by everyone.

Note that, there is also another series for genpd and qcom drivers
that might make it for v6.9. It may be best to keep all these things
together to avoid conflicts.

Let's see what Greg/Rafael thinks about patch 1 first though.

>
> for:
>
> drivers/remoteproc/imx_rproc.c
> drivers/remoteproc/imx_dsp_rproc.c
>
> Reviewed-by: Mathieu Poirier 

Thanks Mathieu and Iuliana!

[...]

Kind regards
Uffe

[1]
https://lore.kernel.org/all/20240122-gdsc-hwctrl-v4-0-9061e8a7a...@linaro.org/



Re: [PATCH v2 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2024-01-12 Thread Ulf Hansson
On Mon, 8 Jan 2024 at 09:44, Daniel Baluta  wrote:
>
> On Fri, Jan 5, 2024 at 6:02 PM Ulf Hansson  wrote:
> >
> > Updates in v2:
> > - Ccing Daniel Baluta and Iuliana Prodan the NXP remoteproc patches 
> > to
> > requests help with testing.
> > - Fixed NULL pointer bug in patch1, pointed out by Nikunj.
> > - Added some tested/reviewed-by tags.
>
> Thanks for doing this Ulf. I remember that I've tried introducing the
> helpers some time ago
> but got side tracked by other tasks.
>
> https://lore.kernel.org/linux-pm/20200624103247.7115-1-daniel.bal...@oss.nxp.com/t/

Thanks for the pointer, yes I recall that too!

I should have added your suggested-by tag to patch1 in this series,
let me update that if/when I submit a new version!

>
> Will review the series and test the remoteproc part this week.

Thanks a lot, looking forward to your feedback!

Kind regards
Uffe



[PATCH v2 5/5] media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

2024-01-05 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the vcodec PM domains,
by converting into using dev_pm_domain_attach|detach_list().

Cc: Mauro Carvalho Chehab 
Cc: Stanimir Varbanov 
Cc: Vikash Garodia 
Cc: "Bryan O'Donoghue" 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Tested-by: Bryan O'Donoghue 
Reviewed-by: Bryan O'Donoghue 
Signed-off-by: Ulf Hansson 
---

Changes in v2:
- Added tags Bryan's tags.

---
 drivers/media/platform/qcom/venus/core.c  | 12 +++--
 drivers/media/platform/qcom/venus/core.h  |  7 ++-
 .../media/platform/qcom/venus/pm_helpers.c| 48 +++
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c 
b/drivers/media/platform/qcom/venus/core.c
index 9cffe975581b..bd9b474280e4 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -114,7 +115,8 @@ static void venus_sys_error_handler(struct work_struct 
*work)
pm_runtime_put_sync(core->dev);
 
for (i = 0; i < max_attempts; i++) {
-   if (!core->pmdomains[0] || 
!pm_runtime_active(core->pmdomains[0]))
+   if (!core->pmdomains ||
+   !pm_runtime_active(core->pmdomains->pd_devs[0]))
break;
usleep_range(1000, 1500);
}
@@ -705,7 +707,7 @@ static const struct venus_resources sdm845_res_v2 = {
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec1_clks = { "vcodec1_core", "vcodec1_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
.vcodec_pmdomains_num = 3,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 2,
@@ -754,7 +756,7 @@ static const struct venus_resources sc7180_res = {
.clks_num = 3,
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
@@ -811,7 +813,7 @@ static const struct venus_resources sm8250_res = {
.resets_num = 2,
.vcodec0_clks = { "vcodec0_core" },
.vcodec_clks_num = 1,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "mx", NULL },
.vcodec_num = 1,
@@ -870,7 +872,7 @@ static const struct venus_resources sc7280_res = {
.clks_num = 3,
.vcodec0_clks = {"vcodec_core", "vcodec_bus"},
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 4a633261ece4..7ef341bf21cc 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -25,7 +25,6 @@
 
 #define VIDC_CLKS_NUM_MAX  4
 #define VIDC_VCODEC_CLKS_NUM_MAX   2
-#define VIDC_PMDOMAINS_NUM_MAX 3
 #define VIDC_RESETS_NUM_MAX2
 
 extern int venus_fw_debug;
@@ -72,7 +71,7 @@ struct venus_resources {
const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX];
const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
unsigned int vcodec_clks_num;
-   const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
+   const char **vcodec_pmdomains;
unsigned int vcodec_pmdomains_num;
const char **opp_pmdomain;
unsigned int vcodec_num;
@@ -134,7 +133,7 @@ struct venus_format {
  * @video_path: an interconnect handle to video to/from memory path
  * @cpucfg_path: an interconnect handle to cpu configuration path
  * @has_opp_table: does OPP table exist
- * @pmdomains: an array of pmdomains struct device pointers
+ * @pmdomains: a pointer to a list of pmdomains
  * @opp_dl_venus: an device-link for device OPP
  * @opp_pmdomain: an OPP power-domain
  * @resets: an array of reset signals
@@ -187,7 +186,7 @@ struct venus_core {
struct icc_path *video_path;
struct icc_path *cpucfg_path;
bool has_opp_table;
-   st

[PATCH v2 4/5] remoteproc: qcom_q6v5_adsp: Convert to dev_pm_domain_attach|detach_list()

2024-01-05 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the various PM domain
cases, by converting into using dev_pm_domain_attach|detach_list().

As a part of the conversion, we are moving over to use device_links, which
simplifies the runtime PM support too. Moreover, while attaching let's
trust that an already attached single PM domain is the correct one.

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Signed-off-by: Ulf Hansson 
---

Changes in v2:
- None.

Kind regards
Ulf Hansson
---
 drivers/remoteproc/qcom_q6v5_adsp.c | 160 +---
 1 file changed, 73 insertions(+), 87 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c 
b/drivers/remoteproc/qcom_q6v5_adsp.c
index 6c67514cc493..93f9a1537ec6 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -55,8 +55,6 @@
 #define QDSP6SS_CORE_CBCR  0x20
 #define QDSP6SS_SLEEP_CBCR 0x3c
 
-#define QCOM_Q6V5_RPROC_PROXY_PD_MAX   3
-
 #define LPASS_BOOT_CORE_START  BIT(0)
 #define LPASS_BOOT_CMD_START   BIT(0)
 #define LPASS_EFUSE_Q6SS_EVB_SEL 0x0
@@ -74,7 +72,8 @@ struct adsp_pil_data {
 
const char **clk_ids;
int num_clks;
-   const char **proxy_pd_names;
+   const char **pd_names;
+   unsigned int num_pds;
const char *load_state;
 };
 
@@ -110,8 +109,7 @@ struct qcom_adsp {
size_t mem_size;
bool has_iommu;
 
-   struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
-   size_t proxy_pd_count;
+   struct dev_pm_domain_list *pd_list;
 
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_ssr ssr_subdev;
@@ -120,98 +118,92 @@ struct qcom_adsp {
int (*shutdown)(struct qcom_adsp *adsp);
 };
 
-static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
-const char **pd_names)
+static int qcom_rproc_pds_attach(struct qcom_adsp *adsp, const char **pd_names,
+unsigned int num_pds)
 {
-   struct device **devs = adsp->proxy_pds;
-   size_t num_pds = 0;
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_names = pd_names,
+   .num_pd_names = num_pds,
+   };
int ret;
-   int i;
-
-   if (!pd_names)
-   return 0;
 
/* Handle single power domain */
-   if (dev->pm_domain) {
-   devs[0] = dev;
-   pm_runtime_enable(dev);
-   return 1;
-   }
+   if (dev->pm_domain)
+   goto out;
 
-   while (pd_names[num_pds])
-   num_pds++;
+   if (!pd_names)
+   return 0;
 
-   if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
-   return -E2BIG;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   if (ret < 0)
+   return ret;
 
-   for (i = 0; i < num_pds; i++) {
-   devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
-   if (IS_ERR_OR_NULL(devs[i])) {
-   ret = PTR_ERR(devs[i]) ? : -ENODATA;
-   goto unroll_attach;
-   }
-   }
+out:
+   pm_runtime_enable(dev);
+   return 0;
+}
 
-   return num_pds;
+static void qcom_rproc_pds_detach(struct qcom_adsp *adsp)
+{
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
 
-unroll_attach:
-   for (i--; i >= 0; i--)
-   dev_pm_domain_detach(devs[i], false);
+   dev_pm_domain_detach_list(pds);
 
-   return ret;
+   if (dev->pm_domain || pds)
+   pm_runtime_disable(adsp->dev);
 }
 
-static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
- size_t pd_count)
+static int qcom_rproc_pds_enable(struct qcom_adsp *adsp)
 {
struct device *dev = adsp->dev;
-   int i;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
+   int ret, i = 0;
 
-   /* Handle single power domain */
-   if (dev->pm_domain && pd_count) {
-   pm_runtime_disable(dev);
-   return;
-   }
+   if (!dev->pm_domain && !pds)
+   return 0;
 
-   for (i = 0; i < pd_count; i++)
-   dev_pm_domain_detach(pds[i], false);
-}
+   if (dev->pm_domain)
+   dev_pm_genpd_set_performance_state(dev, INT_MAX);
 
-static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
-size_t pd_count)
-{
-   int ret;
-   int i;
-
-   for (i = 0; i < pd_count; i++) {
-   dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
-   ret = pm_runtime_resume_and_get(pds[i]);
-   if (ret < 0) {
-   dev_pm_genpd_set_performance_state(pds[i], 0);
-   

[PATCH v2 3/5] remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-05 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: Iuliana Prodan 
Cc: Daniel Baluta 
Cc: 
Signed-off-by: Ulf Hansson 
---

Changes in v2:
- None.

Iuliana/Daniel I am ccing you to request help with test/review of this change.
Note that, you will need patch 1/5 in the series too, to be able to test this.

Kind regards
Ulf Hansson

---
 drivers/remoteproc/imx_rproc.c | 73 +-
 1 file changed, 9 insertions(+), 64 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 8bb293b9f327..3161f14442bc 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -92,7 +92,6 @@ struct imx_rproc_mem {
 
 static int imx_rproc_xtr_mbox_init(struct rproc *rproc);
 static void imx_rproc_free_mbox(struct rproc *rproc);
-static int imx_rproc_detach_pd(struct rproc *rproc);
 
 struct imx_rproc {
struct device   *dev;
@@ -113,10 +112,8 @@ struct imx_rproc {
u32 rproc_pt;   /* partition id */
u32 rsrc_id;/* resource id */
u32 entry;  /* cpu start address */
-   int num_pd;
u32 core_index;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
 };
 
 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
@@ -853,7 +850,7 @@ static void imx_rproc_put_scu(struct rproc *rproc)
return;
 
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
-   imx_rproc_detach_pd(rproc);
+   dev_pm_domain_detach_list(priv->pd_list);
return;
}
 
@@ -880,72 +877,20 @@ static int imx_rproc_partition_notify(struct 
notifier_block *nb,
 static int imx_rproc_attach_pd(struct imx_rproc *priv)
 {
struct device *dev = priv->dev;
-   int ret, i;
-
-   /*
-* If there is only one power-domain entry, the platform driver 
framework
-* will handle it, no need handle it in this driver.
-*/
-   priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains",
- "#power-domain-cells");
-   if (priv->num_pd <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev), GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_pd; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pd;
-   }
-
-   priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], 
DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME | 
DL_FLAG_RPM_ACTIVE);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pd;
-   }
-   }
-
-   return 0;
-
-detach_pd:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_rproc_detach_pd(struct rproc *rproc)
-{
-   struct imx_rproc *priv = rproc->priv;
-   int i;
+   int ret;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_flags = PD_FLAG_DEV_LINK_ON,
+   };
 
/*
 * If there is only one power-domain entry, the platform driver 
framework
 * will handle it, no need handle it in this driver.
 */
-   if (priv->num_pd <= 1)
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_pd; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   return ret < 0 ? ret : 0;
 }
 
 static int imx_rproc_detect_mode(struct imx_rproc *priv)
-- 
2.34.1




[PATCH v2 2/5] remoteproc: imx_dsp_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-05 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: Iuliana Prodan 
Cc: Daniel Baluta 
Cc: 
Signed-off-by: Ulf Hansson 
---

Changes in v2:
- None.

Iuliana/Daniel I am ccing you to request help with test/review of this change.
Note that, you will need patch 1/5 in the series too, to be able to test this.

Kind regards
Ulf Hansson

---
 drivers/remoteproc/imx_dsp_rproc.c | 82 --
 1 file changed, 9 insertions(+), 73 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c 
b/drivers/remoteproc/imx_dsp_rproc.c
index 8fcda9b74545..0409b7c47d5c 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -103,12 +103,10 @@ enum imx_dsp_rp_mbox_messages {
  * @tx_ch: mailbox tx channel handle
  * @rx_ch: mailbox rx channel handle
  * @rxdb_ch: mailbox rx doorbell channel handle
- * @pd_dev: power domain device
- * @pd_dev_link: power domain device link
+ * @pd_list: power domain list
  * @ipc_handle: System Control Unit ipc handle
  * @rproc_work: work for processing virtio interrupts
  * @pm_comp: completion primitive to sync for suspend response
- * @num_domains: power domain number
  * @flags: control flags
  */
 struct imx_dsp_rproc {
@@ -121,12 +119,10 @@ struct imx_dsp_rproc {
struct mbox_chan*tx_ch;
struct mbox_chan*rx_ch;
struct mbox_chan*rxdb_ch;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
struct imx_sc_ipc   *ipc_handle;
struct work_struct  rproc_work;
struct completion   pm_comp;
-   int num_domains;
u32 flags;
 };
 
@@ -954,74 +950,14 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
 static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv)
 {
struct device *dev = priv->rproc->dev.parent;
-   int ret, i;
-
-   priv->num_domains = of_count_phandle_with_args(dev->of_node,
-  "power-domains",
-  "#power-domain-cells");
-
-   /* If only one domain, then no need to link the device */
-   if (priv->num_domains <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_domains,
- sizeof(*priv->pd_dev),
- GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_domains,
-  sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_domains; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pm;
-   }
-
-   /*
-* device_link_add will check priv->pd_dev[i], if it is
-* NULL, then will break.
-*/
-   priv->pd_dev_link[i] = device_link_add(dev,
-  priv->pd_dev[i],
-  DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pm;
-   }
-   }
-
-   return 0;
-
-detach_pm:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_dsp_detach_pm_domains(struct imx_dsp_rproc *priv)
-{
-   int i;
+   int ret;
 
-   if (priv->num_domains <= 1)
+   /* A single PM domain is already attached. */
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_domains; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, NULL, >pd_list);
+   return ret 

[PATCH v2 1/5] PM: domains: Add helper functions to attach/detach multiple PM domains

2024-01-05 Thread Ulf Hansson
Attaching/detaching of a device to multiple PM domains has started to
become a common operation for many drivers, typically during ->probe() and
->remove(). In most cases, this has lead to lots of boilerplate code in the
drivers.

To fixup up the situation, let's introduce a pair of helper functions,
dev_pm_domain_attach|detach_list(), that driver can use instead of the
open-coding. Note that, it seems reasonable to limit the support for these
helpers to DT based platforms, at it's the only valid use case for now.

Signed-off-by: Ulf Hansson 
---

Changes in v2:
- Fix NULL pointer bug pointed out by Nikunj.

---
 drivers/base/power/common.c | 134 
 include/linux/pm_domain.h   |  38 ++
 2 files changed, 172 insertions(+)

diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 44ec20918a4d..327d168dd37a 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -167,6 +167,115 @@ struct device *dev_pm_domain_attach_by_name(struct device 
*dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
 
+/**
+ * dev_pm_domain_attach_list - Associate a device with its PM domains.
+ * @dev: The device used to lookup the PM domains for.
+ * @data: The data used for attaching to the PM domains.
+ * @list: An out-parameter with an allocated list of attached PM domains.
+ *
+ * This function helps to attach a device to its multiple PM domains. The
+ * caller, which is typically a driver's probe function, may provide a list of
+ * names for the PM domains that we should try to attach the device to, but it
+ * may also provide an empty list, in case the attach should be done for all of
+ * the available PM domains.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the number of attached PM domains or a negative error code in case 
of
+ * a failure. Note that, to detach the list of PM domains, the driver shall 
call
+ * dev_pm_domain_detach_list(), typically during the remove phase.
+ */
+int dev_pm_domain_attach_list(struct device *dev,
+ const struct dev_pm_domain_attach_data *data,
+ struct dev_pm_domain_list **list)
+{
+   struct device_node *np = dev->of_node;
+   struct dev_pm_domain_list *pds;
+   struct device *pd_dev = NULL;
+   int ret, i, num_pds = 0;
+   bool by_id = true;
+   u32 pd_flags = data ? data->pd_flags : 0;
+   u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
+   DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
+
+   if (dev->pm_domain)
+   return -EEXIST;
+
+   /* For now this is limited to OF based platforms. */
+   if (!np)
+   return 0;
+
+   if (data && data->pd_names) {
+   num_pds = data->num_pd_names;
+   by_id = false;
+   } else {
+   num_pds = of_count_phandle_with_args(np, "power-domains",
+"#power-domain-cells");
+   }
+
+   if (num_pds <= 0)
+   return 0;
+
+   pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
+   if (!pds)
+   return -ENOMEM;
+
+   pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
+   GFP_KERNEL);
+   if (!pds->pd_devs)
+   return -ENOMEM;
+
+   pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
+GFP_KERNEL);
+   if (!pds->pd_links)
+   return -ENOMEM;
+
+   if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
+   link_flags |= DL_FLAG_RPM_ACTIVE;
+
+   for (i = 0; i < num_pds; i++) {
+   if (by_id)
+   pd_dev = dev_pm_domain_attach_by_id(dev, i);
+   else
+   pd_dev = dev_pm_domain_attach_by_name(dev,
+   data->pd_names[i]);
+   if (IS_ERR_OR_NULL(pd_dev)) {
+   ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
+   goto err_attach;
+   }
+
+   if (link_flags) {
+   struct device_link *link;
+
+   link = device_link_add(dev, pd_dev, link_flags);
+   if (!link) {
+   ret = -ENODEV;
+   goto err_link;
+   }
+
+   pds->pd_links[i] = link;
+   }
+
+   pds->pd_devs[i] = pd_dev;
+   }
+
+   pds->num_pds = num_pds;
+   *list = pds;
+   return num_pds;
+
+err_link:
+   dev_pm_domain_detach(pd_dev, true);
+err_attach:
+   while (--i >= 0) {
+   if (pds->pd_links[i])
+ 

[PATCH v2 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2024-01-05 Thread Ulf Hansson
Updates in v2:
- Ccing Daniel Baluta and Iuliana Prodan the NXP remoteproc patches to
requests help with testing.
- Fixed NULL pointer bug in patch1, pointed out by Nikunj.
- Added some tested/reviewed-by tags.


Attaching/detaching of a device to multiple PM domains has started to become a
common operation for many drivers, typically during ->probe() and ->remove().
In most cases, this has lead to lots of boilerplate code in the drivers.

This series adds a pair of helper functions to manage the attach/detach of a
device to its multiple PM domains. Moreover, a couple of drivers have been
converted to use the new helpers as a proof of concept.

Note 1)
The changes in the drivers have only been compile tested, while the helpers
have been tested along with a couple of local dummy drivers that I have hacked
up to model both genpd providers and genpd consumers.

Note 2)
I was struggling to make up mind if we should have a separate helper to attach
all available power-domains described in DT, rather than providing "NULL" to the
dev_pm_domain_attach_list(). I decided not to, but please let me know if you
prefer the other option.

Note 3)
For OPP integration, as a follow up I am striving to make the
dev_pm_opp_attach_genpd() redundant. Instead I think we should move towards
using dev_pm_opp_set_config()->_opp_set_required_devs(), which would allow us to
use the helpers that $subject series is adding.

Kind regards
Ulf Hansson


Ulf Hansson (5):
  PM: domains: Add helper functions to attach/detach multiple PM domains
  remoteproc: imx_dsp_rproc: Convert to
dev_pm_domain_attach|detach_list()
  remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
  remoteproc: qcom_q6v5_adsp: Convert to
dev_pm_domain_attach|detach_list()
  media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

 drivers/base/power/common.c   | 134 +++
 drivers/media/platform/qcom/venus/core.c  |  12 +-
 drivers/media/platform/qcom/venus/core.h  |   7 +-
 .../media/platform/qcom/venus/pm_helpers.c|  48 ++
 drivers/remoteproc/imx_dsp_rproc.c|  82 +
 drivers/remoteproc/imx_rproc.c|  73 +---
 drivers/remoteproc/qcom_q6v5_adsp.c   | 160 --
 include/linux/pm_domain.h |  38 +
 8 files changed, 289 insertions(+), 265 deletions(-)

-- 
2.34.1



Re: [PATCH 1/5] PM: domains: Add helper functions to attach/detach multiple PM domains

2024-01-03 Thread Ulf Hansson
On Fri, 29 Dec 2023 at 21:21, Nikunj Kela  wrote:
>
>
> On 12/28/2023 3:41 AM, Ulf Hansson wrote:
> > Attaching/detaching of a device to multiple PM domains has started to
> > become a common operation for many drivers, typically during ->probe() and
> > ->remove(). In most cases, this has lead to lots of boilerplate code in the
> > drivers.
> >
> > To fixup up the situation, let's introduce a pair of helper functions,
> > dev_pm_domain_attach|detach_list(), that driver can use instead of the
> > open-coding. Note that, it seems reasonable to limit the support for these
> > helpers to DT based platforms, at it's the only valid use case for now.
> >
> > Signed-off-by: Ulf Hansson 
> > ---
> >   drivers/base/power/common.c | 133 
> >   include/linux/pm_domain.h   |  38 +++
> >   2 files changed, 171 insertions(+)
> >
> > diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
> > index 44ec20918a4d..1ef51889fc6f 100644
> > --- a/drivers/base/power/common.c
> > +++ b/drivers/base/power/common.c
> > @@ -167,6 +167,114 @@ struct device *dev_pm_domain_attach_by_name(struct 
> > device *dev,
> >   }
> >   EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
> >
> > +/**
> > + * dev_pm_domain_attach_list - Associate a device with its PM domains.
> > + * @dev: The device used to lookup the PM domains for.
> > + * @data: The data used for attaching to the PM domains.
> > + * @list: An out-parameter with an allocated list of attached PM domains.
> > + *
> > + * This function helps to attach a device to its multiple PM domains. The
> > + * caller, which is typically a driver's probe function, may provide a 
> > list of
> > + * names for the PM domains that we should try to attach the device to, 
> > but it
> > + * may also provide an empty list, in case the attach should be done for 
> > all of
> > + * the available PM domains.
> > + *
> > + * Callers must ensure proper synchronization of this function with power
> > + * management callbacks.
> > + *
> > + * Returns the number of attached PM domains or a negative error code in 
> > case of
> > + * a failure. Note that, to detach the list of PM domains, the driver 
> > shall call
> > + * dev_pm_domain_detach_list(), typically during the remove phase.
> > + */
> > +int dev_pm_domain_attach_list(struct device *dev,
> > +   const struct dev_pm_domain_attach_data *data,
> > +   struct dev_pm_domain_list **list)
> > +{
> > + struct device_node *np = dev->of_node;
> > + struct dev_pm_domain_list *pds;
> > + struct device *pd_dev = NULL;
> > + int ret, i, num_pds = 0;
> > + bool by_id = true;
> > + u32 link_flags = data && data->pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
> > + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
> > +
> > + if (dev->pm_domain)
> > + return -EEXIST;
> > +
> > + /* For now this is limited to OF based platforms. */
> > + if (!np)
> > + return 0;
> > +
> > + if (data && data->pd_names) {
> > + num_pds = data->num_pd_names;
> > + by_id = false;
> > + } else {
> > + num_pds = of_count_phandle_with_args(np, "power-domains",
> > +  "#power-domain-cells");
> > + }
> > +
> > + if (num_pds <= 0)
> > + return 0;
> > +
> > + pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
> > + if (!pds)
> > + return -ENOMEM;
> > +
> > + pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
> > + GFP_KERNEL);
> > + if (!pds->pd_devs)
> > + return -ENOMEM;
> > +
> > + pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
> > +  GFP_KERNEL);
> > + if (!pds->pd_links)
> > + return -ENOMEM;
> > +
> > + if (link_flags && data->pd_flags & PD_FLAG_DEV_LINK_ON)
>
> Since data is optional, this check results in crash if data is NULL. Thanks

Thanks for spotting this! I certainly tested that option too, but must
have been on some earlier internal version. :-)

I will iterate the series tomorrow to fix this up.

[...]

Kind regards
Uffe



Re: [PATCH 3/5] remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()

2024-01-03 Thread Ulf Hansson
On Tue, 2 Jan 2024 at 19:41, Mathieu Poirier  wrote:
>
> Hi Ulf,
>
> I'm in agreement with the modifications done to imx_rproc.c and 
> imx_dsp_rproc.c.
> There is one thing I am ambivalent on, please see below.
>
> On Thu, Dec 28, 2023 at 12:41:55PM +0100, Ulf Hansson wrote:
> > Let's avoid the boilerplate code to manage the multiple PM domain case, by
> > converting into using dev_pm_domain_attach|detach_list().
> >
> > Cc: Mathieu Poirier 
> > Cc: Bjorn Andersson 
> > Cc: Shawn Guo 
> > Cc: Sascha Hauer 
> > Cc: 
> > Signed-off-by: Ulf Hansson 
> > ---
> >  drivers/remoteproc/imx_rproc.c | 73 +-
> >  1 file changed, 9 insertions(+), 64 deletions(-)
> >
> > diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> > index 8bb293b9f327..3161f14442bc 100644
> > --- a/drivers/remoteproc/imx_rproc.c
> > +++ b/drivers/remoteproc/imx_rproc.c
> > @@ -92,7 +92,6 @@ struct imx_rproc_mem {
> >
> >  static int imx_rproc_xtr_mbox_init(struct rproc *rproc);
> >  static void imx_rproc_free_mbox(struct rproc *rproc);
> > -static int imx_rproc_detach_pd(struct rproc *rproc);
> >
> >  struct imx_rproc {
> >   struct device   *dev;
> > @@ -113,10 +112,8 @@ struct imx_rproc {
> >   u32 rproc_pt;   /* partition id */
> >   u32 rsrc_id;/* resource id */
> >   u32 entry;  /* cpu start address 
> > */
> > - int num_pd;
> >   u32 core_index;
> > - struct device   **pd_dev;
> > - struct device_link  **pd_dev_link;
> > + struct dev_pm_domain_list   *pd_list;
> >  };
> >
> >  static const struct imx_rproc_att imx_rproc_att_imx93[] = {
> > @@ -853,7 +850,7 @@ static void imx_rproc_put_scu(struct rproc *rproc)
> >   return;
> >
> >   if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
> > - imx_rproc_detach_pd(rproc);
> > + dev_pm_domain_detach_list(priv->pd_list);
> >   return;
> >   }
> >
> > @@ -880,72 +877,20 @@ static int imx_rproc_partition_notify(struct 
> > notifier_block *nb,
> >  static int imx_rproc_attach_pd(struct imx_rproc *priv)
> >  {
> >   struct device *dev = priv->dev;
> > - int ret, i;
> > -
> > - /*
> > -  * If there is only one power-domain entry, the platform driver 
> > framework
> > -  * will handle it, no need handle it in this driver.
> > -  */
> > - priv->num_pd = of_count_phandle_with_args(dev->of_node, 
> > "power-domains",
> > -   "#power-domain-cells");
> > - if (priv->num_pd <= 1)
> > - return 0;
>
> In function dev_pm_domain_attach_list(), this condition is "<= 0" rather than
> "<= 1".  As such the association between the device and power domain will be
> done twice when there is a single power domain, i.e once by the core and once 
> in
> dev_pm_domain_attach_list().
>
> I am assuming the runtime PM subsystem is smart enough to deal with this kind 
> of
> situation but would like a confirmation.

Thanks for reviewing!

To cover the the single PM domain case, imx_rproc_attach_pd() is
returning 0 when dev->pm_domain has been assigned. Moreover,
dev_pm_domain_attach_list() doesn't allow attaching in the single PM
domain case, as it returns -EEXIST if "dev->pm_domain" is already
assigned.

Did that make sense to you?

[...]

Kind regards
Uffe



[PATCH 5/5] media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

2023-12-28 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the vcodec PM domains,
by converting into using dev_pm_domain_attach|detach_list().

Cc: Mauro Carvalho Chehab 
Cc: Stanimir Varbanov 
Cc: Vikash Garodia 
Cc: "Bryan O'Donoghue" 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Signed-off-by: Ulf Hansson 
---
 drivers/media/platform/qcom/venus/core.c  | 12 +++--
 drivers/media/platform/qcom/venus/core.h  |  7 ++-
 .../media/platform/qcom/venus/pm_helpers.c| 48 +++
 3 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c 
b/drivers/media/platform/qcom/venus/core.c
index 9cffe975581b..bd9b474280e4 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -114,7 +115,8 @@ static void venus_sys_error_handler(struct work_struct 
*work)
pm_runtime_put_sync(core->dev);
 
for (i = 0; i < max_attempts; i++) {
-   if (!core->pmdomains[0] || 
!pm_runtime_active(core->pmdomains[0]))
+   if (!core->pmdomains ||
+   !pm_runtime_active(core->pmdomains->pd_devs[0]))
break;
usleep_range(1000, 1500);
}
@@ -705,7 +707,7 @@ static const struct venus_resources sdm845_res_v2 = {
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec1_clks = { "vcodec1_core", "vcodec1_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
.vcodec_pmdomains_num = 3,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 2,
@@ -754,7 +756,7 @@ static const struct venus_resources sc7180_res = {
.clks_num = 3,
.vcodec0_clks = { "vcodec0_core", "vcodec0_bus" },
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
@@ -811,7 +813,7 @@ static const struct venus_resources sm8250_res = {
.resets_num = 2,
.vcodec0_clks = { "vcodec0_core" },
.vcodec_clks_num = 1,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "mx", NULL },
.vcodec_num = 1,
@@ -870,7 +872,7 @@ static const struct venus_resources sc7280_res = {
.clks_num = 3,
.vcodec0_clks = {"vcodec_core", "vcodec_bus"},
.vcodec_clks_num = 2,
-   .vcodec_pmdomains = { "venus", "vcodec0" },
+   .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
.opp_pmdomain = (const char *[]) { "cx", NULL },
.vcodec_num = 1,
diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 4a633261ece4..7ef341bf21cc 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -25,7 +25,6 @@
 
 #define VIDC_CLKS_NUM_MAX  4
 #define VIDC_VCODEC_CLKS_NUM_MAX   2
-#define VIDC_PMDOMAINS_NUM_MAX 3
 #define VIDC_RESETS_NUM_MAX2
 
 extern int venus_fw_debug;
@@ -72,7 +71,7 @@ struct venus_resources {
const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX];
const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
unsigned int vcodec_clks_num;
-   const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX];
+   const char **vcodec_pmdomains;
unsigned int vcodec_pmdomains_num;
const char **opp_pmdomain;
unsigned int vcodec_num;
@@ -134,7 +133,7 @@ struct venus_format {
  * @video_path: an interconnect handle to video to/from memory path
  * @cpucfg_path: an interconnect handle to cpu configuration path
  * @has_opp_table: does OPP table exist
- * @pmdomains: an array of pmdomains struct device pointers
+ * @pmdomains: a pointer to a list of pmdomains
  * @opp_dl_venus: an device-link for device OPP
  * @opp_pmdomain: an OPP power-domain
  * @resets: an array of reset signals
@@ -187,7 +186,7 @@ struct venus_core {
struct icc_path *video_path;
struct icc_path *cpucfg_path;
bool has_opp_table;
-   struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
+   struct dev_pm_domain_list *pmdomains;
struct devi

[PATCH 4/5] remoteproc: qcom_q6v5_adsp: Convert to dev_pm_domain_attach|detach_list()

2023-12-28 Thread Ulf Hansson
Let's avoid some of the boilerplate code to manage the various PM domain
cases, by converting into using dev_pm_domain_attach|detach_list().

As a part of the conversion, we are moving over to use device_links, which
simplifies the runtime PM support too. Moreover, while attaching let's
trust that an already attached single PM domain is the correct one.

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Konrad Dybcio 
Cc: 
Signed-off-by: Ulf Hansson 
---
 drivers/remoteproc/qcom_q6v5_adsp.c | 160 +---
 1 file changed, 73 insertions(+), 87 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c 
b/drivers/remoteproc/qcom_q6v5_adsp.c
index 6c67514cc493..93f9a1537ec6 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -55,8 +55,6 @@
 #define QDSP6SS_CORE_CBCR  0x20
 #define QDSP6SS_SLEEP_CBCR 0x3c
 
-#define QCOM_Q6V5_RPROC_PROXY_PD_MAX   3
-
 #define LPASS_BOOT_CORE_START  BIT(0)
 #define LPASS_BOOT_CMD_START   BIT(0)
 #define LPASS_EFUSE_Q6SS_EVB_SEL 0x0
@@ -74,7 +72,8 @@ struct adsp_pil_data {
 
const char **clk_ids;
int num_clks;
-   const char **proxy_pd_names;
+   const char **pd_names;
+   unsigned int num_pds;
const char *load_state;
 };
 
@@ -110,8 +109,7 @@ struct qcom_adsp {
size_t mem_size;
bool has_iommu;
 
-   struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
-   size_t proxy_pd_count;
+   struct dev_pm_domain_list *pd_list;
 
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_ssr ssr_subdev;
@@ -120,98 +118,92 @@ struct qcom_adsp {
int (*shutdown)(struct qcom_adsp *adsp);
 };
 
-static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
-const char **pd_names)
+static int qcom_rproc_pds_attach(struct qcom_adsp *adsp, const char **pd_names,
+unsigned int num_pds)
 {
-   struct device **devs = adsp->proxy_pds;
-   size_t num_pds = 0;
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_names = pd_names,
+   .num_pd_names = num_pds,
+   };
int ret;
-   int i;
-
-   if (!pd_names)
-   return 0;
 
/* Handle single power domain */
-   if (dev->pm_domain) {
-   devs[0] = dev;
-   pm_runtime_enable(dev);
-   return 1;
-   }
+   if (dev->pm_domain)
+   goto out;
 
-   while (pd_names[num_pds])
-   num_pds++;
+   if (!pd_names)
+   return 0;
 
-   if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
-   return -E2BIG;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   if (ret < 0)
+   return ret;
 
-   for (i = 0; i < num_pds; i++) {
-   devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
-   if (IS_ERR_OR_NULL(devs[i])) {
-   ret = PTR_ERR(devs[i]) ? : -ENODATA;
-   goto unroll_attach;
-   }
-   }
+out:
+   pm_runtime_enable(dev);
+   return 0;
+}
 
-   return num_pds;
+static void qcom_rproc_pds_detach(struct qcom_adsp *adsp)
+{
+   struct device *dev = adsp->dev;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
 
-unroll_attach:
-   for (i--; i >= 0; i--)
-   dev_pm_domain_detach(devs[i], false);
+   dev_pm_domain_detach_list(pds);
 
-   return ret;
+   if (dev->pm_domain || pds)
+   pm_runtime_disable(adsp->dev);
 }
 
-static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
- size_t pd_count)
+static int qcom_rproc_pds_enable(struct qcom_adsp *adsp)
 {
struct device *dev = adsp->dev;
-   int i;
+   struct dev_pm_domain_list *pds = adsp->pd_list;
+   int ret, i = 0;
 
-   /* Handle single power domain */
-   if (dev->pm_domain && pd_count) {
-   pm_runtime_disable(dev);
-   return;
-   }
+   if (!dev->pm_domain && !pds)
+   return 0;
 
-   for (i = 0; i < pd_count; i++)
-   dev_pm_domain_detach(pds[i], false);
-}
+   if (dev->pm_domain)
+   dev_pm_genpd_set_performance_state(dev, INT_MAX);
 
-static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
-size_t pd_count)
-{
-   int ret;
-   int i;
-
-   for (i = 0; i < pd_count; i++) {
-   dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
-   ret = pm_runtime_resume_and_get(pds[i]);
-   if (ret < 0) {
-   dev_pm_genpd_set_performance_state(pds[i], 0);
-   goto unroll_pd_votes;
-   }
+   while (pds && i <

[PATCH 3/5] remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()

2023-12-28 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: 
Signed-off-by: Ulf Hansson 
---
 drivers/remoteproc/imx_rproc.c | 73 +-
 1 file changed, 9 insertions(+), 64 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 8bb293b9f327..3161f14442bc 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -92,7 +92,6 @@ struct imx_rproc_mem {
 
 static int imx_rproc_xtr_mbox_init(struct rproc *rproc);
 static void imx_rproc_free_mbox(struct rproc *rproc);
-static int imx_rproc_detach_pd(struct rproc *rproc);
 
 struct imx_rproc {
struct device   *dev;
@@ -113,10 +112,8 @@ struct imx_rproc {
u32 rproc_pt;   /* partition id */
u32 rsrc_id;/* resource id */
u32 entry;  /* cpu start address */
-   int num_pd;
u32 core_index;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
 };
 
 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
@@ -853,7 +850,7 @@ static void imx_rproc_put_scu(struct rproc *rproc)
return;
 
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
-   imx_rproc_detach_pd(rproc);
+   dev_pm_domain_detach_list(priv->pd_list);
return;
}
 
@@ -880,72 +877,20 @@ static int imx_rproc_partition_notify(struct 
notifier_block *nb,
 static int imx_rproc_attach_pd(struct imx_rproc *priv)
 {
struct device *dev = priv->dev;
-   int ret, i;
-
-   /*
-* If there is only one power-domain entry, the platform driver 
framework
-* will handle it, no need handle it in this driver.
-*/
-   priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains",
- "#power-domain-cells");
-   if (priv->num_pd <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev), GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, 
sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_pd; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pd;
-   }
-
-   priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], 
DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME | 
DL_FLAG_RPM_ACTIVE);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pd;
-   }
-   }
-
-   return 0;
-
-detach_pd:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_rproc_detach_pd(struct rproc *rproc)
-{
-   struct imx_rproc *priv = rproc->priv;
-   int i;
+   int ret;
+   struct dev_pm_domain_attach_data pd_data = {
+   .pd_flags = PD_FLAG_DEV_LINK_ON,
+   };
 
/*
 * If there is only one power-domain entry, the platform driver 
framework
 * will handle it, no need handle it in this driver.
 */
-   if (priv->num_pd <= 1)
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_pd; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, _data, >pd_list);
+   return ret < 0 ? ret : 0;
 }
 
 static int imx_rproc_detect_mode(struct imx_rproc *priv)
-- 
2.34.1




[PATCH 2/5] remoteproc: imx_dsp_rproc: Convert to dev_pm_domain_attach|detach_list()

2023-12-28 Thread Ulf Hansson
Let's avoid the boilerplate code to manage the multiple PM domain case, by
converting into using dev_pm_domain_attach|detach_list().

Cc: Mathieu Poirier 
Cc: Bjorn Andersson 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: 
Signed-off-by: Ulf Hansson 
---
 drivers/remoteproc/imx_dsp_rproc.c | 82 --
 1 file changed, 9 insertions(+), 73 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c 
b/drivers/remoteproc/imx_dsp_rproc.c
index 8fcda9b74545..0409b7c47d5c 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -103,12 +103,10 @@ enum imx_dsp_rp_mbox_messages {
  * @tx_ch: mailbox tx channel handle
  * @rx_ch: mailbox rx channel handle
  * @rxdb_ch: mailbox rx doorbell channel handle
- * @pd_dev: power domain device
- * @pd_dev_link: power domain device link
+ * @pd_list: power domain list
  * @ipc_handle: System Control Unit ipc handle
  * @rproc_work: work for processing virtio interrupts
  * @pm_comp: completion primitive to sync for suspend response
- * @num_domains: power domain number
  * @flags: control flags
  */
 struct imx_dsp_rproc {
@@ -121,12 +119,10 @@ struct imx_dsp_rproc {
struct mbox_chan*tx_ch;
struct mbox_chan*rx_ch;
struct mbox_chan*rxdb_ch;
-   struct device   **pd_dev;
-   struct device_link  **pd_dev_link;
+   struct dev_pm_domain_list   *pd_list;
struct imx_sc_ipc   *ipc_handle;
struct work_struct  rproc_work;
struct completion   pm_comp;
-   int num_domains;
u32 flags;
 };
 
@@ -954,74 +950,14 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
 static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv)
 {
struct device *dev = priv->rproc->dev.parent;
-   int ret, i;
-
-   priv->num_domains = of_count_phandle_with_args(dev->of_node,
-  "power-domains",
-  "#power-domain-cells");
-
-   /* If only one domain, then no need to link the device */
-   if (priv->num_domains <= 1)
-   return 0;
-
-   priv->pd_dev = devm_kmalloc_array(dev, priv->num_domains,
- sizeof(*priv->pd_dev),
- GFP_KERNEL);
-   if (!priv->pd_dev)
-   return -ENOMEM;
-
-   priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_domains,
-  sizeof(*priv->pd_dev_link),
-  GFP_KERNEL);
-   if (!priv->pd_dev_link)
-   return -ENOMEM;
-
-   for (i = 0; i < priv->num_domains; i++) {
-   priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-   if (IS_ERR(priv->pd_dev[i])) {
-   ret = PTR_ERR(priv->pd_dev[i]);
-   goto detach_pm;
-   }
-
-   /*
-* device_link_add will check priv->pd_dev[i], if it is
-* NULL, then will break.
-*/
-   priv->pd_dev_link[i] = device_link_add(dev,
-  priv->pd_dev[i],
-  DL_FLAG_STATELESS |
-  DL_FLAG_PM_RUNTIME);
-   if (!priv->pd_dev_link[i]) {
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   ret = -EINVAL;
-   goto detach_pm;
-   }
-   }
-
-   return 0;
-
-detach_pm:
-   while (--i >= 0) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return ret;
-}
-
-static int imx_dsp_detach_pm_domains(struct imx_dsp_rproc *priv)
-{
-   int i;
+   int ret;
 
-   if (priv->num_domains <= 1)
+   /* A single PM domain is already attached. */
+   if (dev->pm_domain)
return 0;
 
-   for (i = 0; i < priv->num_domains; i++) {
-   device_link_del(priv->pd_dev_link[i]);
-   dev_pm_domain_detach(priv->pd_dev[i], false);
-   }
-
-   return 0;
+   ret = dev_pm_domain_attach_list(dev, NULL, >pd_list);
+   return ret < 0 ? ret : 0;
 }
 
 /**
@@ -1153,7 +1089,7 @@ static int imx_dsp_rproc_probe(struct platform_device 
*pdev)
return 0;
 
 err_detach_domains:
-   imx_dsp_detach_pm_domains(priv);
+   dev_pm_domain_detach_list(priv->pd_list);
 err_put_rproc:
rproc_fre

[PATCH 1/5] PM: domains: Add helper functions to attach/detach multiple PM domains

2023-12-28 Thread Ulf Hansson
Attaching/detaching of a device to multiple PM domains has started to
become a common operation for many drivers, typically during ->probe() and
->remove(). In most cases, this has lead to lots of boilerplate code in the
drivers.

To fixup up the situation, let's introduce a pair of helper functions,
dev_pm_domain_attach|detach_list(), that driver can use instead of the
open-coding. Note that, it seems reasonable to limit the support for these
helpers to DT based platforms, at it's the only valid use case for now.

Signed-off-by: Ulf Hansson 
---
 drivers/base/power/common.c | 133 
 include/linux/pm_domain.h   |  38 +++
 2 files changed, 171 insertions(+)

diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 44ec20918a4d..1ef51889fc6f 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -167,6 +167,114 @@ struct device *dev_pm_domain_attach_by_name(struct device 
*dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
 
+/**
+ * dev_pm_domain_attach_list - Associate a device with its PM domains.
+ * @dev: The device used to lookup the PM domains for.
+ * @data: The data used for attaching to the PM domains.
+ * @list: An out-parameter with an allocated list of attached PM domains.
+ *
+ * This function helps to attach a device to its multiple PM domains. The
+ * caller, which is typically a driver's probe function, may provide a list of
+ * names for the PM domains that we should try to attach the device to, but it
+ * may also provide an empty list, in case the attach should be done for all of
+ * the available PM domains.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the number of attached PM domains or a negative error code in case 
of
+ * a failure. Note that, to detach the list of PM domains, the driver shall 
call
+ * dev_pm_domain_detach_list(), typically during the remove phase.
+ */
+int dev_pm_domain_attach_list(struct device *dev,
+ const struct dev_pm_domain_attach_data *data,
+ struct dev_pm_domain_list **list)
+{
+   struct device_node *np = dev->of_node;
+   struct dev_pm_domain_list *pds;
+   struct device *pd_dev = NULL;
+   int ret, i, num_pds = 0;
+   bool by_id = true;
+   u32 link_flags = data && data->pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
+   DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
+
+   if (dev->pm_domain)
+   return -EEXIST;
+
+   /* For now this is limited to OF based platforms. */
+   if (!np)
+   return 0;
+
+   if (data && data->pd_names) {
+   num_pds = data->num_pd_names;
+   by_id = false;
+   } else {
+   num_pds = of_count_phandle_with_args(np, "power-domains",
+"#power-domain-cells");
+   }
+
+   if (num_pds <= 0)
+   return 0;
+
+   pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
+   if (!pds)
+   return -ENOMEM;
+
+   pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
+   GFP_KERNEL);
+   if (!pds->pd_devs)
+   return -ENOMEM;
+
+   pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
+GFP_KERNEL);
+   if (!pds->pd_links)
+   return -ENOMEM;
+
+   if (link_flags && data->pd_flags & PD_FLAG_DEV_LINK_ON)
+   link_flags |= DL_FLAG_RPM_ACTIVE;
+
+   for (i = 0; i < num_pds; i++) {
+   if (by_id)
+   pd_dev = dev_pm_domain_attach_by_id(dev, i);
+   else
+   pd_dev = dev_pm_domain_attach_by_name(dev,
+   data->pd_names[i]);
+   if (IS_ERR_OR_NULL(pd_dev)) {
+   ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
+   goto err_attach;
+   }
+
+   if (link_flags) {
+   struct device_link *link;
+
+   link = device_link_add(dev, pd_dev, link_flags);
+   if (!link) {
+   ret = -ENODEV;
+   goto err_link;
+   }
+
+   pds->pd_links[i] = link;
+   }
+
+   pds->pd_devs[i] = pd_dev;
+   }
+
+   pds->num_pds = num_pds;
+   *list = pds;
+   return num_pds;
+
+err_link:
+   dev_pm_domain_detach(pd_dev, true);
+err_attach:
+   while (--i >= 0) {
+   if (pds->pd_links[i])
+   device_link_del(pds->pd_links[i]);
+   dev_pm_domain_detach(pds->pd_devs[i], tru

[PATCH 0/5] PM: domains: Add helpers for multi PM domains to avoid open-coding

2023-12-28 Thread Ulf Hansson
Attaching/detaching of a device to multiple PM domains has started to become a
common operation for many drivers, typically during ->probe() and ->remove().
In most cases, this has lead to lots of boilerplate code in the drivers.

This series adds a pair of helper functions to manage the attach/detach of a
device to its multiple PM domains. Moreover, a couple of drivers have been
converted to use the new helpers as a proof of concept.

Note 1)
The changes in the drivers have only been compile tested, while the helpers
have been tested along with a couple of local dummy drivers that I have hacked
up to model both genpd providers and genpd consumers.

Note 2)
I was struggling to make up mind if we should have a separate helper to attach
all available power-domains described in DT, rather than providing "NULL" to the
dev_pm_domain_attach_list(). I decided not to, but please let me know if you
prefer the other option.

Note 3)
For OPP integration, as a follow up I am striving to make the
dev_pm_opp_attach_genpd() redundant. Instead I think we should move towards
using dev_pm_opp_set_config()->_opp_set_required_devs(), which would allow us to
use the helpers that $subject series is adding.

Kind regards
Ulf Hansson

Ulf Hansson (5):
  PM: domains: Add helper functions to attach/detach multiple PM domains
  remoteproc: imx_dsp_rproc: Convert to
dev_pm_domain_attach|detach_list()
  remoteproc: imx_rproc: Convert to dev_pm_domain_attach|detach_list()
  remoteproc: qcom_q6v5_adsp: Convert to
dev_pm_domain_attach|detach_list()
  media: venus: Convert to dev_pm_domain_attach|detach_list() for vcodec

 drivers/base/power/common.c   | 133 +++
 drivers/media/platform/qcom/venus/core.c  |  12 +-
 drivers/media/platform/qcom/venus/core.h  |   7 +-
 .../media/platform/qcom/venus/pm_helpers.c|  48 ++
 drivers/remoteproc/imx_dsp_rproc.c|  82 +
 drivers/remoteproc/imx_rproc.c|  73 +---
 drivers/remoteproc/qcom_q6v5_adsp.c   | 160 --
 include/linux/pm_domain.h |  38 +
 8 files changed, 288 insertions(+), 265 deletions(-)

-- 
2.34.1




Re: [PATCH] dt-bindings: correct white-spaces in examples

2023-11-28 Thread Ulf Hansson
On Fri, 24 Nov 2023 at 10:21, Krzysztof Kozlowski
 wrote:
>
> Use only one and exactly one space around '=' in DTS example.
>
> Signed-off-by: Krzysztof Kozlowski 

Acked-by: Ulf Hansson  # For MMC

Kind regards
Uffe

>
> ---
>
> Merging idea: Rob's DT.
> Should apply cleanly on Rob's for-next.
> ---
>  .../devicetree/bindings/auxdisplay/hit,hd44780.yaml   | 2 +-
>  .../devicetree/bindings/clock/baikal,bt1-ccu-pll.yaml | 2 +-
>  Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml | 6 +++---
>  .../devicetree/bindings/iio/adc/qcom,spmi-iadc.yaml   | 2 +-
>  .../devicetree/bindings/iio/adc/qcom,spmi-rradc.yaml  | 2 +-
>  .../interrupt-controller/st,stih407-irq-syscfg.yaml   | 4 ++--
>  Documentation/devicetree/bindings/mmc/arm,pl18x.yaml  | 2 +-
>  Documentation/devicetree/bindings/net/sff,sfp.yaml| 2 +-
>  .../devicetree/bindings/pci/toshiba,visconti-pcie.yaml| 2 +-
>  .../bindings/pinctrl/renesas,rzg2l-pinctrl.yaml   | 6 +++---
>  .../devicetree/bindings/power/supply/richtek,rt9455.yaml  | 8 
>  .../devicetree/bindings/regulator/mps,mp5416.yaml | 4 ++--
>  .../devicetree/bindings/regulator/mps,mpq7920.yaml| 4 ++--
>  .../devicetree/bindings/remoteproc/fsl,imx-rproc.yaml | 8 
>  14 files changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml 
> b/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml
> index fde07e4b119d..406a922a714e 100644
> --- a/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml
> +++ b/Documentation/devicetree/bindings/auxdisplay/hit,hd44780.yaml
> @@ -113,7 +113,7 @@ examples:
>  hd44780 {
>  compatible = "hit,hd44780";
>  display-height-chars = <2>;
> -display-width-chars  = <16>;
> +display-width-chars = <16>;
>  data-gpios = < 4 0>,
>   < 5 0>,
>   < 6 0>,
> diff --git a/Documentation/devicetree/bindings/clock/baikal,bt1-ccu-pll.yaml 
> b/Documentation/devicetree/bindings/clock/baikal,bt1-ccu-pll.yaml
> index 624984d51c10..7f8d98226437 100644
> --- a/Documentation/devicetree/bindings/clock/baikal,bt1-ccu-pll.yaml
> +++ b/Documentation/devicetree/bindings/clock/baikal,bt1-ccu-pll.yaml
> @@ -125,7 +125,7 @@ examples:
>  clk25m: clock-oscillator-25m {
>compatible = "fixed-clock";
>#clock-cells = <0>;
> -  clock-frequency  = <2500>;
> +  clock-frequency = <2500>;
>clock-output-names = "clk25m";
>  };
>  ...
> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml 
> b/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
> index 5fcc8dd012f1..be2616ff9af6 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
> @@ -80,9 +80,9 @@ examples:
>  compatible = "adi,ad7780";
>  reg = <0>;
>
> -avdd-supply  = <_supply>;
> -powerdown-gpios  = < 12 GPIO_ACTIVE_HIGH>;
> -adi,gain-gpios   = <  5 GPIO_ACTIVE_LOW>;
> +avdd-supply = <_supply>;
> +powerdown-gpios = < 12 GPIO_ACTIVE_HIGH>;
> +adi,gain-gpios = <  5 GPIO_ACTIVE_LOW>;
>  adi,filter-gpios = < 15 GPIO_ACTIVE_LOW>;
>  };
>  };
> diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.yaml 
> b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.yaml
> index 73def67fbe01..b6a233cd5f6b 100644
> --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.yaml
> @@ -58,7 +58,7 @@ examples:
>  reg = <0x3600>;
>  interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>;
>  qcom,external-resistor-micro-ohms = <1>;
> -#io-channel-cells  = <1>;
> +#io-channel-cells = <1>;
>  };
>  };
>  ...
> diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-rradc.yaml 
> b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-rradc.yaml
> index b3a626389870..64abe9a4cd9e 100644
> --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-rradc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-rradc.yaml
> @@ -46,6 +46,6 @@ examples:
>  pmic_rradc: adc@4500 {
>  compatible = "qcom,pmi8998-rradc";
>  reg = <0x4500>;
> -#io-

Re: [PATCH 2/2] net: mwifiex: add support for the SD8777 chipset

2023-11-02 Thread Ulf Hansson
On Sun, 29 Oct 2023 at 12:19, Karel Balej  wrote:
>
> Marvell SD8777 is a wireless chipset used for instance in the PXA1908
> SoC found for example in the samsung,coreprimevelte smartphone, with
> which this was tested. The driver seems to be compatible with this
> chipset so enable this support by adding the necessary information based
> on the downstream code.
>
> Signed-off-by: Karel Balej 

Acked-by: Ulf Hansson  # For MMC

Kind regards
Uffe

> ---
>  drivers/net/wireless/marvell/mwifiex/Kconfig |  4 ++--
>  drivers/net/wireless/marvell/mwifiex/sdio.c  | 19 +++
>  drivers/net/wireless/marvell/mwifiex/sdio.h  |  1 +
>  include/linux/mmc/sdio_ids.h |  1 +
>  4 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/Kconfig 
> b/drivers/net/wireless/marvell/mwifiex/Kconfig
> index b182f7155d66..a7bd2c5735f6 100644
> --- a/drivers/net/wireless/marvell/mwifiex/Kconfig
> +++ b/drivers/net/wireless/marvell/mwifiex/Kconfig
> @@ -10,13 +10,13 @@ config MWIFIEX
>   mwifiex.
>
>  config MWIFIEX_SDIO
> -   tristate "Marvell WiFi-Ex Driver for 
> SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8978/SD8987/SD8997"
> +   tristate "Marvell WiFi-Ex Driver for 
> SD8777/SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8978/SD8987/SD8997"
> depends on MWIFIEX && MMC
> select FW_LOADER
> select WANT_DEV_COREDUMP
> help
>   This adds support for wireless adapters based on Marvell
> - 8786/8787/8797/8887/8897/8977/8978/8987/8997 chipsets with
> + 8777/8786/8787/8797/8887/8897/8977/8978/8987/8997 chipsets with
>   SDIO interface. SD8978 is also known as NXP IW416.
>
>   If you choose to build it as a module, it will be called
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c 
> b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index 774858cfe86f..c55f1f5669cb 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -318,6 +318,21 @@ static const struct mwifiex_sdio_card_reg 
> mwifiex_reg_sd89xx = {
>  0x68, 0x69, 0x6a},
>  };
>
> +static const struct mwifiex_sdio_device mwifiex_sdio_sd8777 = {
> +   .firmware = SD8777_DEFAULT_FW_NAME,
> +   .reg = _reg_sd87xx,
> +   .max_ports = 16,
> +   .mp_agg_pkt_limit = 8,
> +   .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
> +   .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
> +   .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
> +   .supports_sdio_new_mode = false,
> +   .has_control_mask = true,
> +   .can_dump_fw = false,
> +   .can_auto_tdls = false,
> +   .can_ext_scan = true,
> +};
> +
>  static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
> .firmware = SD8786_DEFAULT_FW_NAME,
> .reg = _reg_sd87xx,
> @@ -496,6 +511,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] 
> = {
>  };
>
>  static const struct of_device_id mwifiex_sdio_of_match_table[] 
> __maybe_unused = {
> +   { .compatible = "marvell,sd8777" },
> { .compatible = "marvell,sd8787" },
> { .compatible = "marvell,sd8897" },
> { .compatible = "marvell,sd8978" },
> @@ -924,6 +940,8 @@ static void mwifiex_sdio_coredump(struct device *dev)
>
>  /* WLAN IDs */
>  static const struct sdio_device_id mwifiex_ids[] = {
> +   {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 
> SDIO_DEVICE_ID_MARVELL_8777_WLAN),
> +   .driver_data = (unsigned long)_sdio_sd8777},
> {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 
> SDIO_DEVICE_ID_MARVELL_8786_WLAN),
> .driver_data = (unsigned long) _sdio_sd8786},
> {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 
> SDIO_DEVICE_ID_MARVELL_8787_WLAN),
> @@ -3180,6 +3198,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
>  MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
>  MODULE_VERSION(SDIO_VERSION);
>  MODULE_LICENSE("GPL v2");
> +MODULE_FIRMWARE(SD8777_DEFAULT_FW_NAME);
>  MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
>  MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
>  MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h 
> b/drivers/net/wireless/marvell/mwifiex/sdio.h
> index ae94c172310f..ed92256b2302 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.h
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
> @@ -18,6 +18,7 @@
>
>  #include "main.h"
>
> +#define SD8777_DEFAULT_FW_NAME "mrvl/sd8777_uapsta.bin"
>  #d

Re: [PATCH v1 1/6] mmc: core: Correct descriptions in mmc_of_parse()

2021-04-19 Thread Ulf Hansson
On Mon, 19 Apr 2021 at 13:24, Andy Shevchenko
 wrote:
>
> Since it has been converted to use device property API, the function
> and field descriptions become outdated. Correct them.
>
> Fixes: 73a47a9bb3e2 ("mmc: core: Use device_property_read instead of 
> of_property_read")
> Signed-off-by: Andy Shevchenko 

Series applied for next, thanks!

Kind regards
Uffe

> ---
>  drivers/mmc/core/host.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 9b89a91b6b47..ce030c5aa53c 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -209,8 +209,8 @@ mmc_of_parse_clk_phase(struct mmc_host *host, struct 
> mmc_clk_phase_map *map)
>  EXPORT_SYMBOL(mmc_of_parse_clk_phase);
>
>  /**
> - * mmc_of_parse() - parse host's device-tree node
> - * @host: host whose node should be parsed.
> + * mmc_of_parse() - parse host's device properties
> + * @host: host whose properties should be parsed.
>   *
>   * To keep the rest of the MMC subsystem unaware of whether DT has been
>   * used to to instantiate and configure this host instance or not, we
> --
> 2.30.2
>


Re: [PATCH] mmc: core: Move eMMC cache flushing to a new bus_ops callback

2021-04-19 Thread Ulf Hansson
On Mon, 19 Apr 2021 at 14:46, Avri Altman  wrote:
>
>
> > To prepare to add internal cache management for SD cards, let's start by
> > moving the eMMC specific code into a new ->flush_cache() bus_ops callback.
> >
> > In this way, it becomes more straight-forward to add the SD specific parts,
> > as subsequent changes are about to show.
> >
> > Signed-off-by: Ulf Hansson 
> Reviewed-by: Avri Altman 

Thanks! Patch applied for next.

Kind regards
Uffe


Re: [PATCH v2 1/2] mmc: block: Issue flush only if allowed

2021-04-19 Thread Ulf Hansson
On Sun, 18 Apr 2021 at 08:00, Avri Altman  wrote:
>
> The cache may be flushed to the nonvolatile storage by writing to
> FLUSH_CACHE byte (EXT_CSD byte [32]). When in command queueing mode, the
> cache may be flushed by issuing a CMDQ_TASK_ DEV_MGMT (CMD48) with a
> FLUSH_CACHE op-code.  Either way, verify that The cache function is
> turned ON before doing so.

Avri, thanks for your patch. Overall this looks good to me.

However things are becoming more and more messy in these layers of the
mmc core. In particular, I would like us to take advantage of the
bus_ops callbacks, when eMMC and/or SD specific features need
different implementations.

I have posted a patch [1], that moves the eMMC cache flushing into a
bus_ops callback. Would you mind rebasing this series on top of that?

Kind regards
Uffe

[1]
https://patchwork.kernel.org/project/linux-mmc/patch/20210419122943.68234-1-ulf.hans...@linaro.org/

>
> fixes: 1e8e55b67030 (mmc: block: Add CQE support)
>
> Reported-by: Brendan Peter 
> Tested-by: Brendan Peter 
> Signed-off-by: Avri Altman 
> ---
>  drivers/mmc/core/block.c   | 7 +++
>  drivers/mmc/core/mmc_ops.c | 4 +---
>  drivers/mmc/core/mmc_ops.h | 5 +
>  3 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index fe5892d30778..6800feb70c92 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -1476,6 +1476,11 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue 
> *mq, struct request *req)
> struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
> struct mmc_request *mrq = mmc_blk_cqe_prep_dcmd(mqrq, req);
>
> +   if (mmc_card_mmc(mq->card) && !mmc_flush_allowed(mq->card)) {
> +   blk_mq_end_request(req, BLK_STS_OK);
> +   return -EPERM;
> +   }
> +
> mrq->cmd->opcode = MMC_SWITCH;
> mrq->cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
> (EXT_CSD_FLUSH_CACHE << 16) |
> @@ -2226,6 +2231,8 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue 
> *mq, struct request *req)
> switch (req_op(req)) {
> case REQ_OP_FLUSH:
> ret = mmc_blk_cqe_issue_flush(mq, req);
> +   if (ret == -EPERM)
> +   return MMC_REQ_FINISHED;
> break;
> case REQ_OP_READ:
> case REQ_OP_WRITE:
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f413474f0f80..9c2a665be034 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -967,9 +967,7 @@ int mmc_flush_cache(struct mmc_card *card)
>  {
> int err = 0;
>
> -   if (mmc_card_mmc(card) &&
> -   (card->ext_csd.cache_size > 0) &&
> -   (card->ext_csd.cache_ctrl & 1)) {
> +   if (mmc_card_mmc(card) && mmc_flush_allowed(card)) {
> err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  EXT_CSD_FLUSH_CACHE, 1,
>  MMC_CACHE_FLUSH_TIMEOUT_MS);
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 632009260e51..bf2b315addd7 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -19,6 +19,11 @@ enum mmc_busy_cmd {
>  struct mmc_host;
>  struct mmc_card;
>
> +static inline bool mmc_flush_allowed(struct mmc_card *card)
> +{
> +   return card->ext_csd.cache_size > 0 && (card->ext_csd.cache_ctrl & 1);
> +}
> +
>  int mmc_select_card(struct mmc_card *card);
>  int mmc_deselect_cards(struct mmc_host *host);
>  int mmc_set_dsr(struct mmc_host *host);
> --
> 2.25.1
>


[PATCH] mmc: core: Move eMMC cache flushing to a new bus_ops callback

2021-04-19 Thread Ulf Hansson
To prepare to add internal cache management for SD cards, let's start by
moving the eMMC specific code into a new ->flush_cache() bus_ops callback.

In this way, it becomes more straight-forward to add the SD specific parts,
as subsequent changes are about to show.

Signed-off-by: Ulf Hansson 
---
 drivers/mmc/core/core.c| 11 +++
 drivers/mmc/core/core.h|  2 ++
 drivers/mmc/core/mmc.c | 25 +++--
 drivers/mmc/core/mmc_ops.c | 23 ---
 drivers/mmc/core/mmc_ops.h |  1 -
 5 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f194940c5974..64eb3c8f0d15 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2044,6 +2044,17 @@ int mmc_sw_reset(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_sw_reset);
 
+int mmc_flush_cache(struct mmc_card *card)
+{
+   const struct mmc_bus_ops *bus_ops = card->host->bus_ops;
+
+   if (bus_ops->flush_cache)
+   return bus_ops->flush_cache(card);
+
+   return 0;
+}
+EXPORT_SYMBOL(mmc_flush_cache);
+
 static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
 {
host->f_init = freq;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 8032451abaea..b00012f14671 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -20,6 +20,7 @@ struct mmc_request;
 struct mmc_bus_ops {
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
+   int (*flush_cache)(struct mmc_card *);
int (*pre_suspend)(struct mmc_host *);
int (*suspend)(struct mmc_host *);
int (*resume)(struct mmc_host *);
@@ -98,6 +99,7 @@ bool mmc_is_req_done(struct mmc_host *host, struct 
mmc_request *mrq);
 
 int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq);
 
+int mmc_flush_cache(struct mmc_card *card);
 int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
unsigned int arg);
 int mmc_can_erase(struct mmc_card *card);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 8741271d3971..77c9ca024285 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -28,6 +28,7 @@
 
 #define DEFAULT_CMD6_TIMEOUT_MS500
 #define MIN_CACHE_EN_TIMEOUT_MS 1600
+#define CACHE_FLUSH_TIMEOUT_MS 3 /* 30s */
 
 static const unsigned int tran_exp[] = {
1,  10, 100,1000,
@@ -2029,6 +2030,25 @@ static void mmc_detect(struct mmc_host *host)
}
 }
 
+/*
+ * Flush the internal cache of the eMMC to non-volatile storage.
+ */
+static int _mmc_flush_cache(struct mmc_card *card)
+{
+   int err = 0;
+
+   if (card->ext_csd.cache_size > 0 && card->ext_csd.cache_ctrl & 1) {
+   err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+EXT_CSD_FLUSH_CACHE, 1,
+CACHE_FLUSH_TIMEOUT_MS);
+   if (err)
+   pr_err("%s: cache flush error %d\n",
+   mmc_hostname(card->host), err);
+   }
+
+   return err;
+}
+
 static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 {
int err = 0;
@@ -2040,7 +2060,7 @@ static int _mmc_suspend(struct mmc_host *host, bool 
is_suspend)
if (mmc_card_suspended(host->card))
goto out;
 
-   err = mmc_flush_cache(host->card);
+   err = _mmc_flush_cache(host->card);
if (err)
goto out;
 
@@ -2181,7 +2201,7 @@ static int _mmc_hw_reset(struct mmc_host *host)
 * In the case of recovery, we can't expect flushing the cache to work
 * always, but we have a go and ignore errors.
 */
-   mmc_flush_cache(host->card);
+   _mmc_flush_cache(host->card);
 
if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset &&
 mmc_can_reset(card)) {
@@ -2201,6 +2221,7 @@ static int _mmc_hw_reset(struct mmc_host *host)
 static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
+   .flush_cache = _mmc_flush_cache,
.suspend = mmc_suspend,
.resume = mmc_resume,
.runtime_suspend = mmc_runtime_suspend,
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index f413474f0f80..b03e3cf5dab4 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -20,7 +20,6 @@
 #include "mmc_ops.h"
 
 #define MMC_BKOPS_TIMEOUT_MS   (120 * 1000) /* 120s */
-#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
 #define MMC_SANITIZE_TIMEOUT_MS(240 * 1000) /* 240s */
 
 static const u8 tuning_blk_pattern_4bit[] = {
@@ -960,28 +959,6 @@ void mmc_run_bkops(struct mmc_card *card)
 }
 EXPORT_SYMBOL(mmc_run_bkops);
 
-/*
- * Flush the cache to the non-volatile storage

Re: [PATCH] mmc: core: Don't allocate IDA for OF aliases

2021-04-16 Thread Ulf Hansson
On Fri, 16 Apr 2021 at 19:50, Stephen Boyd  wrote:
>
> Quoting Ulf Hansson (2021-04-16 00:17:10)
> > On Thu, 15 Apr 2021 at 21:29, Stephen Boyd  wrote:
> > >
> > >
> > > Don't think so. The device (with the kobject inside) is removed, and
> > > thus the mmc1 device will be removed, but the kobject's release function
> > > is delayed due to the config. This means that
> > > mmc_host_classdev_release() is called at a later time. The only thing
> > > inside that function is the IDA removal and the kfree of the container
> > > object. Given that nothing else is in that release function I believe it
> > > is safe to skip IDA allocation as it won't be blocking anything in the
> > > reserved alias case.
> > >
> > > Furthermore, when the device is deleted in mmc_remove_host() there could
> > > be other users of the device that haven't called put_device() yet.
> > > Either way, those other users are keeping the device memory alive, but
> > > otherwise device_del() has unlinked it from the various driver core
> > > lists and sysfs has removed it too so it's in a state where code may be
> > > referencing it but it's on the way out so users of the device will not
> > > be able to do much with it during this time.
> >
> > Right, but see more below.
> >
> > >
> > > This sort of problem (if it exists which I don't think it does) would
> > > have been there all along and can't be fixed at this level. When a
> > > device that has an alias calls the mmc_alloc_host() function twice it
> > > gets two different device structures created so there are two distinct
> > > kobjects that will need to be released at some point. The index is
> > > usually different for those two kobjects, but with aliases it turns out
> > > it is the same. When it comes to registering that device with the same
> > > name the second one will fail because a device with that name already
> > > exists on the bus. This would be really hard to do given that it would
> > > need to be the same aliased device in DT calling the mmc_add_host()
> > > function without calling mmc_remove_host() for the first one it added in
> > > between.
> >
> > In fact, we have a few rare corner cases that can trigger KASAN splats
> > when mmc_remove_host() gets executed. Similar splats can be triggered
> > by just doing a sudden card removal. It's especially related to the
> > cases, where a thread holds a reference to the card/host object when
> > it's being removed. I am working on patches to fix these cases, but
> > haven't yet decided on the best solution.
>
> Ok. Can you share the KASAN reports? The memory allocated for this class
> object and associated index from the IDA will be unique for each call
> the mmc_alloc_host() so I don't see how KASAN could be noticing
> something unless a reference to the host is leaking out without the
> proper get_device() call being made to keep the underlying memory from
> being freed.

Removing the host, also means removing the card. Although, as I said,
I need some more time to think of the best solution.

Here's a report, triggered with some manual hacks and by using the
mmc-utils usesland tool.

/mmc status get /dev/mmcblk1
[   95.905913] DEBUG: mmc_blk_open: Let's sleep for 10s..
[   98.806639] mmc1: card 0007 removed
[  105.972139] BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
[  105.979144] Read of size 4 at addr 0a394a28 by task mmc/180
[  105.984945]
[  105.991209] CPU: 2 PID: 180 Comm: mmc Not tainted
5.10.0-rc4-00069-gcc758c8c7127-dirty #5
[  105.992943] Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
[  106.001010] Call trace:
[  106.007799]  dump_backtrace+0x0/0x2b4
[  106.009965]  show_stack+0x18/0x6c
[  106.013779]  dump_stack+0xfc/0x168
[  106.017083]  print_address_description.constprop.0+0x6c/0x488
[  106.020384]  kasan_report+0x118/0x210
[  106.026193]  __asan_load4+0x94/0xd0
[  106.029844]  mmc_blk_get+0x58/0xb8
[  106.033141]  mmc_blk_open+0x7c/0xdc
[  106.036614]  __blkdev_get+0x3b4/0x964
[  106.039996]  blkdev_get+0x64/0x100
[  106.043815]  blkdev_open+0xe8/0x104
[  106.047114]  do_dentry_open+0x234/0x61c
[  106.050498]  vfs_open+0x54/0x64
[  106.054324]  path_openat+0xe04/0x1584
[  106.057450]  do_filp_open+0xe8/0x1e4
[  106.061263]  do_sys_openat2+0x120/0x230
[  106.064911]  __arm64_sys_openat+0xf0/0x15c
[  106.068477]  el0_svc_common.constprop.0+0xac/0x234
[  106.072639]  do_el0_svc+0x84/0xa0
[  106.077410]  el0_sync_handler+0x264/0x270
[  106.080790]  el0_sync+0x174/0x180
[  106.084768]
[  106.088070] Allocated by task 33:
[  106.089647]  stack_trace_save+0x9c/0xdc
[  106.092858]  kasan_save_stack+0x28/0x60

Re: [PATCH v2] mmc: meson-gx: replace WARN_ONCE with dev_warn_once about scatterlist size alignment in block mode

2021-04-16 Thread Ulf Hansson
On Fri, 16 Apr 2021 at 11:43, Neil Armstrong  wrote:
>
> Since commit e085b51c74cc ("mmc: meson-gx: check for scatterlist size 
> alignment in block mode"),
> support for SDIO SD_IO_RW_EXTENDED transferts are properly filtered but some 
> driver
> like brcmfmac still gives a block sg buffer size not aligned with SDIO block,
> triggerring a WARN_ONCE() with scary stacktrace even if the transfer works 
> fine
> but with possible degraded performances.
>
> Simply replace with dev_warn_once() to inform user this should be fixed to 
> avoid
> degraded performance.
>
> This should be ultimately fixed in brcmfmac, but since it's only a 
> performance issue
> the warning should be removed.
>
> Fixes: e085b51c74cc ("mmc: meson-gx: check for scatterlist size alignment in 
> block mode")
> Reported-by: Marek Szyprowski 
> Signed-off-by: Neil Armstrong 

Applied for next, thanks! (I move to fixes if there is another rc on Monday).

Kind regards
Uffe


> ---
> Changes since v1:
> - replace WARN_ONCE with dev_warn_once and explicit the warning message
>
>  drivers/mmc/host/meson-gx-mmc.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
> index eb6c02bc4a02..b8b771b643cc 100644
> --- a/drivers/mmc/host/meson-gx-mmc.c
> +++ b/drivers/mmc/host/meson-gx-mmc.c
> @@ -247,8 +247,9 @@ static void meson_mmc_get_transfer_mode(struct mmc_host 
> *mmc,
>  */
> for_each_sg(data->sg, sg, data->sg_len, i) {
> if (sg->length % data->blksz) {
> -   WARN_ONCE(1, "unaligned sg len %u blksize 
> %u\n",
> - sg->length, data->blksz);
> +   dev_warn_once(mmc_dev(mmc),
> + "unaligned sg len %u blksize 
> %u, disabling descriptor DMA for transfer\n",
> + sg->length, data->blksz);
> return;
> }
> }
> --
> 2.25.1
>


Re: [PATCH] mmc: core: Don't allocate IDA for OF aliases

2021-04-16 Thread Ulf Hansson
On Thu, 15 Apr 2021 at 21:29, Stephen Boyd  wrote:
>
> Quoting Ulf Hansson (2021-04-15 01:56:12)
> > On Tue, 13 Apr 2021 at 02:36, Stephen Boyd  wrote:
> > >
> > > -   err = ida_simple_get(_host_ida, min_idx, max_idx, GFP_KERNEL);
> > > -   if (err < 0) {
> > > -   kfree(host);
> > > -   return NULL;
> > > +   index = ida_simple_get(_host_ida, min_idx, max_idx, 
> > > GFP_KERNEL);
> > > +   if (index < 0) {
> > > +   kfree(host);
> > > +   return NULL;
> > > +   }
> >
> > This means that a DTB that is screwed up in a way that it has two mmc
> > aliases with the same index, would be allowed to use the same index.
> >
> > What will happen when we continue the probe sequence in such a case?
>
> Yeah I thought about this after sending the patch. So the problem would
> be like this right?
>
> aliases {
> mmc1 = 
> mmc1 = 
> };

Correct.

>
> I have good news! DT won't compile it because it saw the same alias
> assigned to twice. I tried it on my sc7180 board.
>
> arch/arm64/boot/dts/qcom/sc7180.dtsi:35.3-18:
> ERROR (duplicate_property_names): /aliases:mmc1: Duplicate property name
> ERROR: Input tree has errors, aborting (use -f to force output)
> arch/arm64/boot/dts/qcom/sc7180-idp.dtb] Error 2
>
> I suppose if someone forced the compilation it may be bad, but do we
> really care?
>
> TL;DR: this seems like it isn't a problem.

Yep, I definitely tend to agree with you here. Thanks for doing the
test and sharing the result.

>
> >
> > > }
> > >
> > > -   host->index = err;
> > > +   host->index = index;
> > >
> > > dev_set_name(>class_dev, "mmc%d", host->index);
> > > host->ws = wakeup_source_register(NULL, 
> > > dev_name(>class_dev));
> >
> > Another concern that could potentially be a problem, is that the
> > "thread" that holds the reference that prevents ida from being
> > removed, how would that react to a new mmc device to become
> > re-registered with the same index?
> >
> > I wonder if we perhaps should return -EPROBE_DEFER instead, when
> > ida_simple_get() fails?
> >
>
> Don't think so. The device (with the kobject inside) is removed, and
> thus the mmc1 device will be removed, but the kobject's release function
> is delayed due to the config. This means that
> mmc_host_classdev_release() is called at a later time. The only thing
> inside that function is the IDA removal and the kfree of the container
> object. Given that nothing else is in that release function I believe it
> is safe to skip IDA allocation as it won't be blocking anything in the
> reserved alias case.
>
> Furthermore, when the device is deleted in mmc_remove_host() there could
> be other users of the device that haven't called put_device() yet.
> Either way, those other users are keeping the device memory alive, but
> otherwise device_del() has unlinked it from the various driver core
> lists and sysfs has removed it too so it's in a state where code may be
> referencing it but it's on the way out so users of the device will not
> be able to do much with it during this time.

Right, but see more below.

>
> This sort of problem (if it exists which I don't think it does) would
> have been there all along and can't be fixed at this level. When a
> device that has an alias calls the mmc_alloc_host() function twice it
> gets two different device structures created so there are two distinct
> kobjects that will need to be released at some point. The index is
> usually different for those two kobjects, but with aliases it turns out
> it is the same. When it comes to registering that device with the same
> name the second one will fail because a device with that name already
> exists on the bus. This would be really hard to do given that it would
> need to be the same aliased device in DT calling the mmc_add_host()
> function without calling mmc_remove_host() for the first one it added in
> between.

In fact, we have a few rare corner cases that can trigger KASAN splats
when mmc_remove_host() gets executed. Similar splats can be triggered
by just doing a sudden card removal. It's especially related to the
cases, where a thread holds a reference to the card/host object when
it's being removed. I am working on patches to fix these cases, but
haven't yet decided on the best solution.

That's the reason why I was thinking that maybe returning
-EPROBE_DEFER could be an option, but certainly I need to think more
about this.

>
> (Sorry if that is long. I'm sort of stream of conciousness writing it to
> you here and not rewriting it to be more concise)

No worries, thanks a lot for sharing your thoughts!

Kind regards
Uffe


Re: [RFC PATCH v3 5/8] cpuidle: Factor-out power domain related code from PSCI domain driver

2021-04-15 Thread Ulf Hansson
; -   of_node_put(node);
> -   return ret;
> -   }
> -   }
> -
> -   return 0;
> -}
> -
>  static bool psci_pd_try_set_osi_mode(void)
>  {
> int ret;
> @@ -244,6 +64,10 @@ static void psci_cpuidle_domain_sync_state(struct device 
> *dev)
> psci_pd_allow_domain_state = true;
>  }
>
> +static struct dt_idle_genpd_ops psci_genpd_ops = {
> +   .parse_state_node = psci_dt_parse_state_node,
> +};
> +
>  static const struct of_device_id psci_of_match[] = {
> { .compatible = "arm,psci-1.0" },
> {}
> @@ -252,48 +76,25 @@ static const struct of_device_id psci_of_match[] = {
>  static int psci_cpuidle_domain_probe(struct platform_device *pdev)
>  {
> struct device_node *np = pdev->dev.of_node;
> -   struct device_node *node;
> bool use_osi;
> -   int ret = 0, pd_count = 0;
> +   int ret = 0;
>
> if (!np)
> return -ENODEV;
>
> /* If OSI mode is supported, let's try to enable it. */
> use_osi = psci_pd_try_set_osi_mode();
> +   if (use_osi)
> +   psci_genpd_ops.power_off = psci_pd_power_off;
>
> -   /*
> -* Parse child nodes for the "#power-domain-cells" property and
> -* initialize a genpd/genpd-of-provider pair when it's found.
> -*/
> -   for_each_child_of_node(np, node) {
> -   if (!of_find_property(node, "#power-domain-cells", NULL))
> -   continue;
> -
> -   ret = psci_pd_init(node, use_osi);
> -   if (ret)
> -   goto put_node;
> -
> -   pd_count++;
> -   }
> -
> -   /* Bail out if not using the hierarchical CPU topology. */
> -   if (!pd_count)
> -   goto no_pd;
> -
> -   /* Link genpd masters/subdomains to model the CPU topology. */
> -   ret = psci_pd_init_topology(np);
> +   /* Generic power domain probing based on DT node. */
> +   ret = dt_idle_genpd_probe(_genpd_ops, np);
> if (ret)
> -   goto remove_pd;
> +   goto no_pd;
>
> pr_info("Initialized CPU PM domain topology\n");
> return 0;
>
> -put_node:
> -   of_node_put(node);
> -remove_pd:
> -   psci_pd_remove();
> -   pr_err("failed to create CPU PM domains ret=%d\n", ret);
>  no_pd:
> if (use_osi)
> psci_set_osi_mode(false);
> @@ -314,28 +115,3 @@ static int __init psci_idle_init_domains(void)
> return platform_driver_register(_cpuidle_domain_driver);
>  }
>  subsys_initcall(psci_idle_init_domains);
> -
> -struct device *psci_dt_attach_cpu(int cpu)
> -{
> -   struct device *dev;
> -
> -   dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
> -   if (IS_ERR_OR_NULL(dev))
> -   return dev;
> -
> -   pm_runtime_irq_safe(dev);
> -   if (cpu_online(cpu))
> -   pm_runtime_get_sync(dev);
> -
> -   dev_pm_syscore_device(dev, true);
> -
> -   return dev;
> -}
> -
> -void psci_dt_detach_cpu(struct device *dev)
> -{
> -   if (IS_ERR_OR_NULL(dev))
> -   return;
> -
> -   dev_pm_domain_detach(dev, false);
> -}
> diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
> index d8e925e84c27..70de1e3c00af 100644
> --- a/drivers/cpuidle/cpuidle-psci.h
> +++ b/drivers/cpuidle/cpuidle-psci.h
> @@ -10,8 +10,19 @@ void psci_set_domain_state(u32 state);
>  int psci_dt_parse_state_node(struct device_node *np, u32 *state);
>
>  #ifdef CONFIG_ARM_PSCI_CPUIDLE_DOMAIN
> -struct device *psci_dt_attach_cpu(int cpu);
> -void psci_dt_detach_cpu(struct device *dev);
> +
> +#include "dt_idle_genpd.h"
> +
> +static inline struct device *psci_dt_attach_cpu(int cpu)
> +{
> +   return dt_idle_genpd_attach_cpu(cpu, "psci");
> +}
> +
> +static inline void psci_dt_detach_cpu(struct device *dev)
> +{
> +   dt_idle_genpd_detach_cpu(dev);
> +}
> +
>  #else
>  static inline struct device *psci_dt_attach_cpu(int cpu) { return NULL; }
>  static inline void psci_dt_detach_cpu(struct device *dev) { }
> diff --git a/drivers/cpuidle/cpuidle-psci-domain.c 
> b/drivers/cpuidle/dt_idle_genpd.c
> similarity index 52%
> copy from drivers/cpuidle/cpuidle-psci-domain.c
> copy to drivers/cpuidle/dt_idle_genpd.c
> index ff2c3f8e4668..805c4c81d60f 100644
> --- a/drivers/cpuidle/cpuidle-psci-domain.c
> +++ b/drivers/cpuidle/dt_idle_genpd.c
> @@ -1,71 +

Re: [PATCH v3] Re-submit of the erase command addition plus removal of MMC_IOC_MULTI_CMD ifndef for erase. Author=Kimito Sakata

2021-04-15 Thread Ulf Hansson
+ Avri

On Fri, 2 Apr 2021 at 01:02,  wrote:
>
> From: Kimito Sakata 
>
> Signed-off-by: Kimito Sakata 

This looks okay to me, but I have looped in Avri who might have some comments.

Kind regards
Uffe

> ---
>  mmc.c  |   8 
>  mmc.h  |  13 +-
>  mmc_cmds.c | 129 +
>  mmc_cmds.h |   1 +
>  4 files changed, 150 insertions(+), 1 deletion(-)
>
> diff --git a/mmc.c b/mmc.c
> index f3d724b..eb2638b 100644
> --- a/mmc.c
> +++ b/mmc.c
> @@ -229,6 +229,14 @@ static struct Command commands[] = {
> "Run Field Firmware Update with  on .\n",
>   NULL
> },
> +   { do_erase, -4,
> +   "erase", " " " " " " "\n"
> +   "Send Erase CMD38 with specific argument to the \n\n"
> +   "NOTE!: This will delete all user data in the specified 
> region of the device\n"
> +   " must be: legacy | discard | secure-erase | "
> +   "secure-trim1 | secure-trim2 | trim \n",
> +   NULL
> +   },
> { 0, 0, 0, 0 }
>  };
>
> diff --git a/mmc.h b/mmc.h
> index 5754a9d..e9766d7 100644
> --- a/mmc.h
> +++ b/mmc.h
> @@ -35,7 +35,15 @@
>  #define MMC_SET_WRITE_PROT 28/* ac   [31:0] data addr   R1b */
>  #define MMC_CLEAR_WRITE_PROT   29/* ac   [31:0] data addr   R1b */
>  #define MMC_SEND_WRITE_PROT_TYPE 31   /* ac   [31:0] data addr   R1  */
> -
> +#define MMC_ERASE_GROUP_START  35/* ac   [31:0] data addr   R1  */
> +#define MMC_ERASE_GROUP_END36/* ac   [31:0] data addr   R1  */
> +#define MMC_ERASE  38/* ac   [31] Secure request
> + [30:16] set to 0
> + [15] Force Garbage Collect 
> request
> + [14:2] set to 0
> + [1] Discard Enable
> + [0] Identify Write Blocks for
> + Erase (or TRIM Enable)  R1b */
>  /*
>   * EXT_CSD fields
>   */
> @@ -62,6 +70,7 @@
>  #define EXT_CSD_CACHE_SIZE_2   251
>  #define EXT_CSD_CACHE_SIZE_1   250
>  #define EXT_CSD_CACHE_SIZE_0   249
> +#define EXT_CSD_SEC_FEATURE_SUPPORT231
>  #define EXT_CSD_BOOT_INFO  228 /* R/W */
>  #define EXT_CSD_HC_ERASE_GRP_SIZE  224
>  #define EXT_CSD_HC_WP_GRP_SIZE 221
> @@ -190,6 +199,8 @@
>  #define EXT_CSD_REV_V4_2   2
>  #define EXT_CSD_REV_V4_1   1
>  #define EXT_CSD_REV_V4_0   0
> +#define EXT_CSD_SEC_GB_CL_EN   (1<<4)
> +#define EXT_CSD_SEC_ER_EN  (1<<0)
>
>
>  /* From kernel linux/mmc/core.h */
> diff --git a/mmc_cmds.c b/mmc_cmds.c
> index 6c24cea..3e36ff2 100644
> --- a/mmc_cmds.c
> +++ b/mmc_cmds.c
> @@ -2514,6 +2514,135 @@ int do_cache_dis(int nargs, char **argv)
> return do_cache_ctrl(0, nargs, argv);
>  }
>
> +static int erase(int dev_fd, __u32 argin, __u32 start, __u32 end)
> +{
> +   int ret = 0;
> +   struct mmc_ioc_multi_cmd *multi_cmd;
> +
> +   multi_cmd = calloc(1, sizeof(struct mmc_ioc_multi_cmd) +
> +  3 * sizeof(struct mmc_ioc_cmd));
> +   if (!multi_cmd) {
> +   perror("Failed to allocate memory");
> +   return -ENOMEM;
> +   }
> +
> +   multi_cmd->num_of_cmds = 3;
> +   /* Set erase start address */
> +   multi_cmd->cmds[0].opcode = MMC_ERASE_GROUP_START;
> +   multi_cmd->cmds[0].arg = start;
> +   multi_cmd->cmds[0].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
> +   multi_cmd->cmds[0].write_flag = 1;
> +
> +   /* Set erase end address */
> +   multi_cmd->cmds[1].opcode = MMC_ERASE_GROUP_END;
> +   multi_cmd->cmds[1].arg = end;
> +   multi_cmd->cmds[1].flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
> +   multi_cmd->cmds[1].write_flag = 1;
> +
> +   /* Send Erase Command */
> +   multi_cmd->cmds[2].opcode = MMC_ERASE;
> +   multi_cmd->cmds[2].arg = argin;
> +   multi_cmd->cmds[2].cmd_timeout_ms = 300*255*255;
> +   multi_cmd->cmds[2].flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
> +   multi_cmd->cmds[2].write_flag = 1;
> +
> +   /* send erase cmd with multi-cmd */
> +   ret = ioctl(dev_fd, MMC_IOC_MULTI_CMD, multi_cmd);
> +   if (ret)
> +   perror("Erase multi-cmd ioctl");
> +
> +   free(multi_cmd);
> +   return ret;
> +}
> +
> +int do_erase(int nargs, char **argv)
> +{
> +   int dev_fd, ret;
> +   char *print_str;
> +   char **eptr = NULL;
> +   __u8 ext_csd[512], checkup_mask = 0;
> +   __u32 arg, start, end;
> +
> +   if (nargs != 5) {
> +   fprintf(stderr, "Usage: erase
> \n");
> +   exit(1);
> +   }
> +
> +   if (strstr(argv[2], "0x") || strstr(argv[2], "0X"))
> +   start = strtol(argv[2], eptr, 16);
> +   else
> + 

Re: [PATCH v2 2/3] mmc: sdhci-s3c: correct kerneldoc of sdhci_s3c_drv_data

2021-04-15 Thread Ulf Hansson
On Thu, 15 Apr 2021 at 10:44, Krzysztof Kozlowski
 wrote:
>
> Correct the name of sdhci_s3c_drv_data structure in kerneldoc:
>
>   drivers/mmc/host/sdhci-s3c.c:143: warning:
> expecting prototype for struct sdhci_s3c_driver_data. Prototype was for 
> struct sdhci_s3c_drv_data instead
>
> Signed-off-by: Krzysztof Kozlowski 
>

Applied for next, thanks!

Kind regards
Uffe


> ---
>
> Changes since v1:
> 1. None
> ---
>  drivers/mmc/host/sdhci-s3c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index 8e1dca625620..a07a8f011741 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -130,7 +130,7 @@ struct sdhci_s3c {
>  };
>
>  /**
> - * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
> + * struct sdhci_s3c_drv_data - S3C SDHCI platform specific driver data
>   * @sdhci_quirks: sdhci host specific quirks.
>   * @no_divider: no or non-standard internal clock divider.
>   *
> --
> 2.25.1
>


Re: [PATCH v2 1/3] mmc: sdhci-s3c: simplify getting of_device_id match data

2021-04-15 Thread Ulf Hansson
On Thu, 15 Apr 2021 at 10:44, Krzysztof Kozlowski
 wrote:
>
> Use of_device_get_match_data() to make the code slightly smaller and to
> remove the of_device_id table forward declaration.
>
> Signed-off-by: Krzysztof Kozlowski 

Applied for next, thanks!

Kind regards
Uffe


>
> ---
>
> Changes since v1:
> 1. Rewrite the commit msg as it is not a NULL pointer dereference.
> ---
>  drivers/mmc/host/sdhci-s3c.c | 12 +++-
>  1 file changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index f48a788a9d3d..8e1dca625620 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -20,6 +20,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -461,19 +462,12 @@ static int sdhci_s3c_parse_dt(struct device *dev,
>  }
>  #endif
>
> -#ifdef CONFIG_OF
> -static const struct of_device_id sdhci_s3c_dt_match[];
> -#endif
> -
>  static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
> struct platform_device *pdev)
>  {
>  #ifdef CONFIG_OF
> -   if (pdev->dev.of_node) {
> -   const struct of_device_id *match;
> -   match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node);
> -   return (struct sdhci_s3c_drv_data *)match->data;
> -   }
> +   if (pdev->dev.of_node)
> +   return (struct sdhci_s3c_drv_data 
> *)of_device_get_match_data(>dev);
>  #endif
> return (struct sdhci_s3c_drv_data *)
> platform_get_device_id(pdev)->driver_data;
> --
> 2.25.1
>


Re: [PATCH v2 3/3] mmc: sdhci-s3c: constify uses of driver/match data

2021-04-15 Thread Ulf Hansson
On Thu, 15 Apr 2021 at 10:44, Krzysztof Kozlowski
 wrote:
>
> The driver data (struct sdhci_s3c_drv_data) stored in of_device_id
> table is allocated as const and used only in const-way.  Skip
> unnecessary const-away casts and convert all users to work with pointer
> to const.  This is both more logical and safer.
>
> Signed-off-by: Krzysztof Kozlowski 
>

Applied for next, thanks!

Kind regards
Uffe


> ---
>
> Changes since v1:
> 1. None
> ---
>  drivers/mmc/host/sdhci-s3c.c | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index a07a8f011741..862f033d235d 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -462,21 +462,21 @@ static int sdhci_s3c_parse_dt(struct device *dev,
>  }
>  #endif
>
> -static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
> +static inline const struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
> struct platform_device *pdev)
>  {
>  #ifdef CONFIG_OF
> if (pdev->dev.of_node)
> -   return (struct sdhci_s3c_drv_data 
> *)of_device_get_match_data(>dev);
> +   return of_device_get_match_data(>dev);
>  #endif
> -   return (struct sdhci_s3c_drv_data *)
> +   return (const struct sdhci_s3c_drv_data *)
> platform_get_device_id(pdev)->driver_data;
>  }
>
>  static int sdhci_s3c_probe(struct platform_device *pdev)
>  {
> struct s3c_sdhci_platdata *pdata;
> -   struct sdhci_s3c_drv_data *drv_data;
> +   const struct sdhci_s3c_drv_data *drv_data;
> struct device *dev = >dev;
> struct sdhci_host *host;
> struct sdhci_s3c *sc;
> @@ -761,7 +761,7 @@ static const struct platform_device_id 
> sdhci_s3c_driver_ids[] = {
>  MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
>
>  #ifdef CONFIG_OF
> -static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
> +static const struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
> .no_divider = true,
>  };
>
> --
> 2.25.1
>


Re: [PATCH v1 0/2] Let sanitize not retry in case of timeout/failure

2021-04-15 Thread Ulf Hansson
On Wed, 14 Apr 2021 at 23:22, Bean Huo  wrote:
>
> From: Bean Huo 
>
>
> Bean Huo (2):
>   mmc: core: Add a retries parameter to __mmc_switch function
>   mmc: core: Let sanitize not retry in case of timeout/failure
>
>  drivers/mmc/core/mmc.c | 22 +++---
>  drivers/mmc/core/mmc_ops.c | 11 ++-
>  drivers/mmc/core/mmc_ops.h |  2 +-
>  3 files changed, 18 insertions(+), 17 deletions(-)

Applied for next, thanks!

Kind regards
Uffe


Re: [PATCH] mmc: sdhci-pci-gli: Enlarge ASPM L1 entry delay of GL975x

2021-04-15 Thread Ulf Hansson
On Thu, 15 Apr 2021 at 05:23, Ben Chuang  wrote:
>
> GL975x enters ASPM L1 state after a short idle in default.
> Enlarge the idle period to 7.9us for improving the R/W performance.
>
> Signed-off-by: Ben Chuang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-pci-gli.c | 32 
>  1 file changed, 32 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c 
> b/drivers/mmc/host/sdhci-pci-gli.c
> index eb1ebb67e113..592d79082f58 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -22,6 +22,10 @@
>  #define   GLI_9750_WT_EN_ON0x1
>  #define   GLI_9750_WT_EN_OFF   0x0
>
> +#define SDHCI_GLI_9750_CFG2  0x848
> +#define   SDHCI_GLI_9750_CFG2_L1DLYGENMASK(28, 24)
> +#define   GLI_9750_CFG2_L1DLY_VALUE0x1F
> +
>  #define SDHCI_GLI_9750_DRIVING  0x860
>  #define   SDHCI_GLI_9750_DRIVING_1GENMASK(11, 0)
>  #define   SDHCI_GLI_9750_DRIVING_2GENMASK(27, 26)
> @@ -113,6 +117,10 @@
>  #define   PCI_GLI_9755_LFCLKGENMASK(14, 12)
>  #define   PCI_GLI_9755_DMACLK   BIT(29)
>
> +#define PCI_GLI_9755_CFG2  0x48
> +#define   PCI_GLI_9755_CFG2_L1DLYGENMASK(28, 24)
> +#define   GLI_9755_CFG2_L1DLY_VALUE  0x1F
> +
>  #define PCI_GLI_9755_PLL0x64
>  #define   PCI_GLI_9755_PLL_LDIV   GENMASK(9, 0)
>  #define   PCI_GLI_9755_PLL_PDIV   GENMASK(14, 12)
> @@ -408,6 +416,22 @@ static void sdhci_gl9750_set_clock(struct sdhci_host 
> *host, unsigned int clock)
> sdhci_enable_clk(host, clk);
>  }
>
> +static void gl9750_hw_setting(struct sdhci_host *host)
> +{
> +   u32 value;
> +
> +   gl9750_wt_on(host);
> +
> +   value = sdhci_readl(host, SDHCI_GLI_9750_CFG2);
> +   value &= ~SDHCI_GLI_9750_CFG2_L1DLY;
> +   /* set ASPM L1 entry delay to 7.9us */
> +   value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY,
> +   GLI_9750_CFG2_L1DLY_VALUE);
> +   sdhci_writel(host, value, SDHCI_GLI_9750_CFG2);
> +
> +   gl9750_wt_off(host);
> +}
> +
>  static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
>  {
> int ret;
> @@ -555,6 +579,13 @@ static void gl9755_hw_setting(struct sdhci_pci_slot 
> *slot)
> value &= ~PCI_GLI_9755_SCP_DIS;
> pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value);
>
> +   pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, );
> +   value &= ~PCI_GLI_9755_CFG2_L1DLY;
> +   /* set ASPM L1 entry delay to 7.9us */
> +   value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY,
> +   GLI_9755_CFG2_L1DLY_VALUE);
> +   pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value);
> +
> gl9755_wt_off(pdev);
>  }
>
> @@ -562,6 +593,7 @@ static int gli_probe_slot_gl9750(struct sdhci_pci_slot 
> *slot)
>  {
> struct sdhci_host *host = slot->host;
>
> +   gl9750_hw_setting(host);
> gli_pcie_enable_msi(slot);
> slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> sdhci_enable_v4_mode(host);
> --
> 2.30.0
>


Re: [PATCH] memstick: r592: remove unused variable

2021-04-15 Thread Ulf Hansson
On Wed, 14 Apr 2021 at 04:21, Jiapeng Chong
 wrote:
>
> Fix the following clang warning:
>
> drivers/memstick/host/r592.c:363:6: warning: variable ‘len’ set but not
> used [-Wunused-but-set-variable].
>
> Reported-by: Abaci Robot 
> Signed-off-by: Jiapeng Chong 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/memstick/host/r592.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
> index d2ef463..026fada 100644
> --- a/drivers/memstick/host/r592.c
> +++ b/drivers/memstick/host/r592.c
> @@ -360,12 +360,11 @@ static void r592_write_fifo_pio(struct r592_device *dev,
>  static void r592_flush_fifo_write(struct r592_device *dev)
>  {
> u8 buffer[4] = { 0 };
> -   int len;
>
> if (kfifo_is_empty(>pio_fifo))
> return;
>
> -   len = kfifo_out(>pio_fifo, buffer, 4);
> +   kfifo_out(>pio_fifo, buffer, 4);
> r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer);
>  }
>
> --
> 1.8.3.1
>


Re: [PATCH] mmc: meson-gx: remove useless warning about scatterlist size alignment in block mode

2021-04-15 Thread Ulf Hansson
On Wed, 14 Apr 2021 at 12:00, Neil Armstrong  wrote:
>
> Since commit e085b51c74cc ("mmc: meson-gx: check for scatterlist size 
> alignment in block mode"),
> support for SDIO SD_IO_RW_EXTENDED transferts are properly filtered but some 
> driver
> like brcmfmac still gives a block sg buffer size not aligned with SDIO block,
> triggerring a warning even if the transfer works in degraded mode.
>
> This should be ultimately fixed in brcmfmac, but since it's only a 
> performance issue
> the warning should be removed.
>
> Fixes: e085b51c74cc ("mmc: meson-gx: check for scatterlist size alignment in 
> block mode")
> Reported-by: Marek Szyprowski 
> Signed-off-by: Neil Armstrong 
> ---
>  drivers/mmc/host/meson-gx-mmc.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
> index eb6c02bc4a02..6bc151045843 100644
> --- a/drivers/mmc/host/meson-gx-mmc.c
> +++ b/drivers/mmc/host/meson-gx-mmc.c
> @@ -246,11 +246,8 @@ static void meson_mmc_get_transfer_mode(struct mmc_host 
> *mmc,
>  * size, otherwise chain mode could not be used.
>  */
> for_each_sg(data->sg, sg, data->sg_len, i) {
> -   if (sg->length % data->blksz) {
> -   WARN_ONCE(1, "unaligned sg len %u blksize 
> %u\n",
> - sg->length, data->blksz);

Rather than removing this warning, perhaps an option could be to use
dev_warn_once() instead?

> +   if (sg->length % data->blksz)
> return;
> -   }
> }
> }
>

Kind regards
Uffe


Re: [PATCH] mmc: core: Don't allocate IDA for OF aliases

2021-04-15 Thread Ulf Hansson
On Tue, 13 Apr 2021 at 02:36, Stephen Boyd  wrote:
>
> There's a chance that the IDA allocated in mmc_alloc_host() is not freed
> for some time because it's freed as part of a class' release function
> (see mmc_host_classdev_release() where the IDA is freed). If another
> thread is holding a reference to the class, then only once all balancing
> device_put() calls (in turn calling kobject_put()) have been made will
> the IDA be released and usable again.
>
> Normally this isn't a problem because the kobject is released before
> anything else that may want to use the same number tries to again, but
> with CONFIG_DEBUG_KOBJECT_RELEASE=y and OF aliases it becomes pretty
> easy to try to allocate an alias from the IDA twice while the first time
> it was allocated is still pending a call to ida_simple_remove(). It's
> also possible to trigger it by using CONFIG_DEBUG_KOBJECT_RELEASE and
> probe defering a driver at boot that calls mmc_alloc_host() before
> trying to get resources that may defer likes clks or regulators.

Thanks for a very nice description of the problem.

>
> Instead of allocating from the IDA in this scenario, let's just skip it
> if we know this is an OF alias. The number is already "claimed" and
> devices that aren't using OF aliases won't try to use the claimed
> numbers anyway (see mmc_first_nonreserved_index()). This should avoid
> any issues with mmc_alloc_host() returning failures from the
> ida_simple_get() in the case that we're using an OF alias.

At first glance, this seems like a good idea, but I am not completely
sure, yet. See more below.

>
> Cc: Matthias Schiffer 
> Cc: Sujit Kautkar 
> Reported-by: Zubin Mithra 
> Fixes: fa2d0aa96941 ("mmc: core: Allow setting slot index via device tree 
> alias")
> Signed-off-by: Stephen Boyd 
> ---
>  drivers/mmc/core/host.c | 20 ++--
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 9b89a91b6b47..137b4a769f62 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -39,7 +39,8 @@ static void mmc_host_classdev_release(struct device *dev)
>  {
> struct mmc_host *host = cls_dev_to_mmc_host(dev);
> wakeup_source_unregister(host->ws);
> -   ida_simple_remove(_host_ida, host->index);
> +   if (of_alias_get_id(host->parent->of_node, "mmc") < 0)
> +   ida_simple_remove(_host_ida, host->index);
> kfree(host);
>  }
>
> @@ -444,7 +445,7 @@ static int mmc_first_nonreserved_index(void)
>   */
>  struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
>  {
> -   int err;
> +   int index;
> struct mmc_host *host;
> int alias_id, min_idx, max_idx;
>
> @@ -457,20 +458,19 @@ struct mmc_host *mmc_alloc_host(int extra, struct 
> device *dev)
>
> alias_id = of_alias_get_id(dev->of_node, "mmc");
> if (alias_id >= 0) {
> -   min_idx = alias_id;
> -   max_idx = alias_id + 1;
> +   index = alias_id;
> } else {
> min_idx = mmc_first_nonreserved_index();
> max_idx = 0;
> -   }
>
> -   err = ida_simple_get(_host_ida, min_idx, max_idx, GFP_KERNEL);
> -   if (err < 0) {
> -   kfree(host);
> -   return NULL;
> +   index = ida_simple_get(_host_ida, min_idx, max_idx, 
> GFP_KERNEL);
> +   if (index < 0) {
> +   kfree(host);
> +   return NULL;
> +   }

This means that a DTB that is screwed up in a way that it has two mmc
aliases with the same index, would be allowed to use the same index.

What will happen when we continue the probe sequence in such a case?

> }
>
> -   host->index = err;
> +   host->index = index;
>
> dev_set_name(>class_dev, "mmc%d", host->index);
> host->ws = wakeup_source_register(NULL, dev_name(>class_dev));

Another concern that could potentially be a problem, is that the
"thread" that holds the reference that prevents ida from being
removed, how would that react to a new mmc device to become
re-registered with the same index?

I wonder if we perhaps should return -EPROBE_DEFER instead, when
ida_simple_get() fails?

Kind regards
Uffe


Re: [PATCH v5 08/24] wfx: add bus_sdio.c

2021-04-12 Thread Ulf Hansson
On Wed, 7 Apr 2021 at 14:00, Kalle Valo  wrote:
>
> Ulf Hansson  writes:
>
> >> If I follow what has been done in other drivers I would write something
> >> like:
> >>
> >>   static int wfx_sdio_suspend(struct device *dev)
> >>   {
> >>   struct sdio_func *func = dev_to_sdio_func(dev);
> >>   struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
> >>
> >>   config_reg_write_bits(bus->core, CFG_IRQ_ENABLE_DATA, 0);
> >>   // Necessary to keep device firmware in RAM
> >>   return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
> >
> > This will tell the mmc/sdio core to keep the SDIO card powered on
> > during system suspend. Thus, it doesn't need to re-initialize it at
> > system resume - and the firmware should not need to be re-programmed.
> >
> > On the other hand, if you don't plan to support system wakeups, it
> > would probably be better to power off the card, to avoid wasting
> > energy while the system is suspended. I assume that means you need to
> > re-program the firmware as well. Normally, it's these kinds of things
> > that need to be managed from a ->resume() callback.
>
> Many mac80211 drivers do so that the device is powered off during
> interface down (ifconfig wlan0 down), and as mac80211 does interface
> down automatically during suspend, suspend then works without extra
> handlers.

That sounds simple. :-)

Would you mind elaborating on what is actually being powered off at
interface down - and thus also I am curious what happens at a typical
interface up?

Even if we don't want to use system wakeups (wake-on-lan), the SDIO
core and the SDIO func driver still need to somewhat agree on how to
manage the power for the card during system suspend, I think.

For example, for a non-removable SDIO card, the SDIO/MMC core may
decide to power off the card in system suspend. Then it needs to
restore power to the card and re-initialize it at system resume, of
course. This doesn't mean that the actual corresponding struct device
for it, gets removed/re-added, thus the SDIO func driver isn't being
re-probed after the system has resumed. Although, since the SDIO card
was re-initialized, it's likely that the FW may need to be
re-programmed after the system has been resumed.

Are you saying that re-programming the FW is always happening at
interface up, when there are none system suspend/resume callbacks
assigned for the SDIO func driver?

Kind regards
Uffe


Re: [PATCH -next] mmc: sdhci-st: Remove unnecessary error log

2021-04-12 Thread Ulf Hansson
On Fri, 9 Apr 2021 at 04:28, Laibin Qiu  wrote:
>
> devm_ioremap_resource() has recorded error log, so it's
> unnecessary to record log again.
>
> Reported-by: Hulk Robot 
> Signed-off-by: Laibin Qiu 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-st.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
> index 78941ac3a1d6..d41582c21aa3 100644
> --- a/drivers/mmc/host/sdhci-st.c
> +++ b/drivers/mmc/host/sdhci-st.c
> @@ -400,10 +400,8 @@ static int sdhci_st_probe(struct platform_device *pdev)
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>"top-mmc-delay");
> pdata->top_ioaddr = devm_ioremap_resource(>dev, res);
> -   if (IS_ERR(pdata->top_ioaddr)) {
> -   dev_warn(>dev, "FlashSS Top Dly registers not 
> available");
> +   if (IS_ERR(pdata->top_ioaddr))
> pdata->top_ioaddr = NULL;
> -   }
>
> pltfm_host->clk = clk;
> pdata->icnclk = icnclk;
> --
> 2.25.1
>


Re: [PATCH -next] mmc: owl-mmc: Remove unnecessary error log

2021-04-12 Thread Ulf Hansson
On Fri, 9 Apr 2021 at 04:24, Laibin Qiu  wrote:
>
> devm_ioremap_resource() has recorded error log, so it's
> unnecessary to record log again.
>
> Reported-by: Hulk Robot 
> Signed-off-by: Laibin Qiu 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/owl-mmc.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c
> index 5490962dc8e5..3dc143b03939 100644
> --- a/drivers/mmc/host/owl-mmc.c
> +++ b/drivers/mmc/host/owl-mmc.c
> @@ -581,7 +581,6 @@ static int owl_mmc_probe(struct platform_device *pdev)
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> owl_host->base = devm_ioremap_resource(>dev, res);
> if (IS_ERR(owl_host->base)) {
> -   dev_err(>dev, "Failed to remap registers\n");
> ret = PTR_ERR(owl_host->base);
> goto err_free_host;
> }
> --
> 2.25.1
>


Re: [PATCH -next] mmc: sdhci-msm: Remove unnecessary error log

2021-04-12 Thread Ulf Hansson
On Fri, 9 Apr 2021 at 03:44, Jia Yang  wrote:
>
> devm_ioremap_resource() has recorded error log, so it's
> unnecessary to record log again.
>
> Reported-by: Hulk Robot 
> Signed-off-by: Jia Yang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-msm.c | 8 ++--
>  1 file changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index d170c919e6e4..e44b7a66b73c 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -1863,7 +1863,6 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host 
> *msm_host,
> struct mmc_host *mmc = msm_host->mmc;
> struct device *dev = mmc_dev(mmc);
> struct resource *res;
> -   int err;
>
> if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))
> return 0;
> @@ -1881,11 +1880,8 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host 
> *msm_host,
> }
>
> msm_host->ice_mem = devm_ioremap_resource(dev, res);
> -   if (IS_ERR(msm_host->ice_mem)) {
> -   err = PTR_ERR(msm_host->ice_mem);
> -   dev_err(dev, "Failed to map ICE registers; err=%d\n", err);
> -   return err;
> -   }
> +   if (IS_ERR(msm_host->ice_mem))
> +   return PTR_ERR(msm_host->ice_mem);
>
> if (!sdhci_msm_ice_supported(msm_host))
> goto disable;
> --
> 2.25.1
>


Re: [RESEND, PATCH] mmc: sdhci-pci-gli: Improve GL9763E L1 entry delay to increase battery life

2021-04-12 Thread Ulf Hansson
On Wed, 7 Apr 2021 at 11:35, Ben Chuang  wrote:
>
> From: Ben Chuang 
>
> For GL9763E, although there is the best performance at the maximum delay.
> Change the value to 20us in order to have better power consumption.
> This change may reduce the maximum performance by 10%.
>
> Signed-off-by: Ben Chuang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-pci-gli.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c 
> b/drivers/mmc/host/sdhci-pci-gli.c
> index 4a0f69b97a78..3b0a049d4124 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -90,7 +90,7 @@
>
>  #define PCIE_GLI_9763E_CFG2  0x8A4
>  #define   GLI_9763E_CFG2_L1DLY GENMASK(28, 19)
> -#define   GLI_9763E_CFG2_L1DLY_MAX 0x3FF
> +#define   GLI_9763E_CFG2_L1DLY_MID 0x50
>
>  #define PCIE_GLI_9763E_MMC_CTRL  0x960
>  #define   GLI_9763E_HS400_SLOW BIT(3)
> @@ -802,8 +802,8 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
>
> pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, );
> value &= ~GLI_9763E_CFG2_L1DLY;
> -   /* set ASPM L1 entry delay to 260us */
> -   value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MAX);
> +   /* set ASPM L1 entry delay to 20us */
> +   value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID);
> pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value);
>
> pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, );
> --
> 2.30.0
>


Re: [PATCH 1/3] dt-bindings: mmc: iproc-sdhci: Convert to json-schema

2021-04-12 Thread Ulf Hansson
On Tue, 6 Apr 2021 at 12:48, Nicolas Saenz Julienne  wrote:
>
> Convert the brcm,iproc-sdhci binding to DT schema format using json-schema
>
> Signed-off-by: Nicolas Saenz Julienne 

Applied for next, thanks! (I guess patch2 and patch3 needs a re-spin?)

Kind regards
Uffe


>
> ---
>
>  .../bindings/mmc/brcm,iproc-sdhci.yaml| 63 +++
>  .../bindings/mmc/brcm,sdhci-iproc.txt | 37 ---
>  2 files changed, 63 insertions(+), 37 deletions(-)
>  create mode 100644 
> Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml
>  delete mode 100644 Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
>
> diff --git a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml 
> b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml
> new file mode 100644
> index ..6f569fbfa134
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml
> @@ -0,0 +1,63 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mmc/brcm,iproc-sdhci.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom IPROC SDHCI controller
> +
> +maintainers:
> +  - Ray Jui 
> +  - Scott Branden 
> +  - Nicolas Saenz Julienne 
> +
> +allOf:
> +  - $ref: mmc-controller.yaml#
> +
> +properties:
> +  compatible:
> +enum:
> +  - brcm,bcm2835-sdhci
> +  - brcm,bcm2711-emmc2
> +  - brcm,sdhci-iproc-cygnus
> +  - brcm,sdhci-iproc
> +
> +  reg:
> +minItems: 1
> +
> +  interrupts:
> +maxItems: 1
> +
> +  clocks:
> +maxItems: 1
> +description:
> +  Handle to core clock for the sdhci controller.
> +
> +  sdhci,auto-cmd12:
> +type: boolean
> +description: Specifies that controller should use auto CMD12
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +#include 
> +#include 
> +#include 
> +
> +mmc@18041000 {
> +  compatible = "brcm,sdhci-iproc-cygnus";
> +  reg = <0x18041000 0x100>;
> +  interrupts = ;
> +  clocks = <_clks BCM_CYGNUS_LCPLL0_SDIO_CLK>;
> +  bus-width = <4>;
> +  sdhci,auto-cmd12;
> +  no-1-8-v;
> +};
> +...
> diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt 
> b/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
> deleted file mode 100644
> index 09d87cc1182a..
> --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -Broadcom IPROC SDHCI controller
> -
> -This file documents differences between the core properties described
> -by mmc.txt and the properties that represent the IPROC SDHCI controller.
> -
> -Required properties:
> -- compatible : Should be one of the following
> -  "brcm,bcm2835-sdhci"
> -  "brcm,bcm2711-emmc2"
> -  "brcm,sdhci-iproc-cygnus"
> -  "brcm,sdhci-iproc"
> -
> -Use brcm2835-sdhci for the eMMC controller on the BCM2835 (Raspberry Pi) and
> -bcm2711-emmc2 for the additional eMMC2 controller on BCM2711.
> -
> -Use sdhci-iproc-cygnus for Broadcom SDHCI Controllers
> -restricted to 32bit host accesses to SDHCI registers.
> -
> -Use sdhci-iproc for Broadcom SDHCI Controllers that allow standard
> -8, 16, 32-bit host access to SDHCI register.
> -
> -- clocks : The clock feeding the SDHCI controller.
> -
> -Optional properties:
> -  - sdhci,auto-cmd12: specifies that controller should use auto CMD12.
> -
> -Example:
> -
> -sdhci0: sdhci@18041000 {
> -   compatible = "brcm,sdhci-iproc-cygnus";
> -   reg = <0x18041000 0x100>;
> -   interrupts = ;
> -   clocks = <_clks BCM_CYGNUS_LCPLL0_SDIO_CLK>;
> -   bus-width = <4>;
> -   sdhci,auto-cmd12;
> -   no-1-8-v;
> -};
> --
> 2.30.2
>


Re: [PATCH] mmc: moxart: Remove unused variable 'dma_time' and 'pio_time'

2021-04-12 Thread Ulf Hansson
On Fri, 2 Apr 2021 at 11:53, Yang Li  wrote:
>
> Fixes the following W=1 kernel build warning(s):
>
> drivers/mmc/host/moxart-mmc.c:257:7: warning: variable ‘dma_time’ set
> but not used
> drivers/mmc/host/moxart-mmc.c:395:7: warning: variable ‘pio_time’ set
> but not used
>
> Reported-by: Abaci Robot 
> Signed-off-by: Yang Li 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/moxart-mmc.c | 10 --
>  1 file changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
> index 89bff4e..bde2988 100644
> --- a/drivers/mmc/host/moxart-mmc.c
> +++ b/drivers/mmc/host/moxart-mmc.c
> @@ -257,7 +257,6 @@ static void moxart_dma_complete(void *param)
>  static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host 
> *host)
>  {
> u32 len, dir_slave;
> -   long dma_time;
> struct dma_async_tx_descriptor *desc = NULL;
> struct dma_chan *dma_chan;
>
> @@ -294,8 +293,8 @@ static void moxart_transfer_dma(struct mmc_data *data, 
> struct moxart_host *host)
>
> data->bytes_xfered += host->data_remain;
>
> -   dma_time = wait_for_completion_interruptible_timeout(
> -  >dma_complete, host->timeout);
> +   wait_for_completion_interruptible_timeout(>dma_complete,
> + host->timeout);
>
> dma_unmap_sg(dma_chan->device->dev,
>  data->sg, data->sg_len,
> @@ -395,7 +394,6 @@ static void moxart_prepare_data(struct moxart_host *host)
>  static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  {
> struct moxart_host *host = mmc_priv(mmc);
> -   long pio_time;
> unsigned long flags;
> u32 status;
>
> @@ -431,8 +429,8 @@ static void moxart_request(struct mmc_host *mmc, struct 
> mmc_request *mrq)
> spin_unlock_irqrestore(>lock, flags);
>
> /* PIO transfers start from interrupt. */
> -   pio_time = wait_for_completion_interruptible_timeout(
> -  >pio_complete, host->timeout);
> +   
> wait_for_completion_interruptible_timeout(>pio_complete,
> + 
> host->timeout);
>
> spin_lock_irqsave(>lock, flags);
> }
> --
> 1.8.3.1
>


Re: [PATCH v3 1/2] mmc: core: Pass down user specified timeout value to sanitize

2021-04-12 Thread Ulf Hansson
On Fri, 2 Apr 2021 at 11:24, Bean Huo  wrote:
>
> From: Bean Huo 
>
> As the density increases, the 4-minute timeout value for
> sanitize is no longer feasible. At the same time, devices
> of different densities have different timeout values, and it is
> difficult to obtain a unified standard timeout value. Therefore,
> it is better to pass down user-specified sanitize timeout value.
>
> Signed-off-by: Bean Huo 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/core/block.c   | 2 +-
>  drivers/mmc/core/mmc_ops.c | 7 +--
>  drivers/mmc/core/mmc_ops.h | 2 +-
>  3 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index fe5892d30778..8bfd4d95b386 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -539,7 +539,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
> struct mmc_blk_data *md,
>
> if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
> (cmd.opcode == MMC_SWITCH))
> -   return mmc_sanitize(card);
> +   return mmc_sanitize(card, idata->ic.cmd_timeout_ms);
>
> mmc_wait_for_req(card->host, );
>
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f413474f0f80..ccca067db993 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -1010,7 +1010,7 @@ int mmc_cmdq_disable(struct mmc_card *card)
>  }
>  EXPORT_SYMBOL_GPL(mmc_cmdq_disable);
>
> -int mmc_sanitize(struct mmc_card *card)
> +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms)
>  {
> struct mmc_host *host = card->host;
> int err;
> @@ -1020,12 +1020,15 @@ int mmc_sanitize(struct mmc_card *card)
> return -EOPNOTSUPP;
> }
>
> +   if (!timeout_ms)
> +   timeout_ms = MMC_SANITIZE_TIMEOUT_MS;
> +
> pr_debug("%s: Sanitize in progress...\n", mmc_hostname(host));
>
> mmc_retune_hold(host);
>
> err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START,
> -1, MMC_SANITIZE_TIMEOUT_MS);
> +1, timeout_ms);
> if (err)
> pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), 
> err);
>
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 632009260e51..1ed0d0375780 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -46,7 +46,7 @@ void mmc_run_bkops(struct mmc_card *card);
>  int mmc_flush_cache(struct mmc_card *card);
>  int mmc_cmdq_enable(struct mmc_card *card);
>  int mmc_cmdq_disable(struct mmc_card *card);
> -int mmc_sanitize(struct mmc_card *card);
> +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms);
>
>  #endif
>
> --
> 2.25.1
>


Re: [PATCH v3 2/2] mmc: core: Let sanitize not retry in case of timeout/failure

2021-04-12 Thread Ulf Hansson
On Fri, 2 Apr 2021 at 11:24, Bean Huo  wrote:
>
> From: Bean Huo 
>
> Not any commands need to retry in case of timeout/failure.
> Currently, the sanitize command is issued by the IOCTL interface,
> and once its timeouts, the user normally decides to retry or not .
> Just blindly retry three times sanitize in the driver, it doesn't
> help sanitize retry succeed in the end, on the contrary, it only
> makes the user feel sanitize timeouts after 12 minutes.
>
> Signed-off-by: Bean Huo 
> ---
>  drivers/mmc/core/block.c   | 13 +++
>  drivers/mmc/core/mmc.c | 47 ++
>  drivers/mmc/core/mmc_ops.c | 19 +++
>  drivers/mmc/core/mmc_ops.h |  4 ++--
>  4 files changed, 47 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 8bfd4d95b386..9778093d7006 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -836,7 +836,7 @@ static inline int mmc_blk_part_switch(struct mmc_card 
> *card,
>
> ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  EXT_CSD_PART_CONFIG, part_config,
> -card->ext_csd.part_time);
> +card->ext_csd.part_time, MMC_CMD_RETRIES);

I would rather not change the mmc_switch() function definition, but
only __mmc_switch(). Just let mmc_switch() pass another in-parameter
(MMC_CMD_RETRIES) to __mmc_switch(), which means all callers of
mmc_switch() doesn't need to get changed, but only callers of
__mmc_switch().

[...]

Kind regards
Uffe


Re: [PATCH] mmc: add quirk to disable eMMC cache for Micron eMMC v5.0 cards

2021-04-12 Thread Ulf Hansson
+ Bean Huo, Luca Porzio

On Thu, 8 Apr 2021 at 19:59, Scott Branden  wrote:
>
> From: Vladimir Olovyannikov 
>
> In certain rare combination of operations, Micron eMMC v5.0 cards
> may experience data errors if internal cache is enabled.
> This may lead to eMMC related data errors.
> Introduce a quirk to disable cache on these eMMC cards.

Can you please elaborate on this, what combinations of operations are
you referring to - and what kind of data errors?

I have also looped in some of the Micron guys, to let them chim in.

>
> Signed-off-by: Vladimir Olovyannikov 
> Signed-off-by: Scott Branden 

Kind regards
Uffe

> ---
>  drivers/mmc/core/card.h   | 5 +
>  drivers/mmc/core/mmc.c| 4 ++--
>  drivers/mmc/core/quirks.h | 8 
>  include/linux/mmc/card.h  | 1 +
>  4 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
> index 7bd392d55cfa..22cea63ac359 100644
> --- a/drivers/mmc/core/card.h
> +++ b/drivers/mmc/core/card.h
> @@ -222,4 +222,9 @@ static inline int mmc_card_broken_hpi(const struct 
> mmc_card *c)
> return c->quirks & MMC_QUIRK_BROKEN_HPI;
>  }
>
> +static inline int mmc_card_broken_cache(const struct mmc_card *c)
> +{
> +   return c->quirks & MMC_QUIRK_BROKEN_CACHE;
> +}
> +
>  #endif
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 8741271d3971..cd83b7f0e59c 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1820,12 +1820,12 @@ static int mmc_init_card(struct mmc_host *host, u32 
> ocr,
>  * sudden power failure tests. Let's extend the timeout to a minimum 
> of
>  * DEFAULT_CACHE_EN_TIMEOUT_MS and do it for all cards.
>  */
> -   if (card->ext_csd.cache_size > 0) {
> +   if (!mmc_card_broken_cache(card) && card->ext_csd.cache_size > 0) {
> unsigned int timeout_ms = MIN_CACHE_EN_TIMEOUT_MS;
>
> timeout_ms = max(card->ext_csd.generic_cmd6_time, timeout_ms);
> err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> -   EXT_CSD_CACHE_CTRL, 1, timeout_ms);
> +EXT_CSD_CACHE_CTRL, 1, timeout_ms);
> if (err && err != -EBADMSG)
> goto free_card;
>
> diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
> index d68e6e513a4f..23972d87c82a 100644
> --- a/drivers/mmc/core/quirks.h
> +++ b/drivers/mmc/core/quirks.h
> @@ -116,6 +116,14 @@ static const struct mmc_fixup __maybe_unused 
> mmc_ext_csd_fixups[] = {
> MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_NUMONYX,
>   0x014e, add_quirk, MMC_QUIRK_BROKEN_HPI, 6),
>
> +   /*
> +* In certain rare combination of operations, Micron eMMC v5.0 cards
> +* may experience data errors if internal cache is enabled.
> +* Disabling cache for these cards eliminates the issue.
> +*/
> +   MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_MICRON,
> + 0x014e, add_quirk, MMC_QUIRK_BROKEN_CACHE, 7),
> +
> END_FIXUP
>  };
>
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index f9ad35dd6012..22f256a4e54e 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -270,6 +270,7 @@ struct mmc_card {
>  #define MMC_QUIRK_BROKEN_IRQ_POLLING   (1<<11) /* Polling SDIO_CCCR_INTx 
> could create a fake interrupt */
>  #define MMC_QUIRK_TRIM_BROKEN  (1<<12) /* Skip trim */
>  #define MMC_QUIRK_BROKEN_HPI   (1<<13) /* Disable broken HPI support 
> */
> +#define MMC_QUIRK_BROKEN_CACHE (1<<14) /* Disable broken cache */
>
> boolreenable_cmdq;  /* Re-enable Command Queue */
>
> --
> 2.17.1
>


Re: [PATCH v1 1/2] dt-bindings: mmc: sdhci-of-aspeed: Add power-gpio and power-switch-gpio

2021-04-12 Thread Ulf Hansson
On Thu, 8 Apr 2021 at 03:52, Steven Lee  wrote:
>
> AST2600-A2 EVB provides the reference design for enabling SD bus power
> and toggling SD bus signal voltage by GPIO pins.
> Add the definition and example for power-gpio and power-switch-gpio
> properties.
>
> In the reference design, GPIOV0 of AST2600-A2 EVB is connected to power
> load switch that providing 3.3v to SD1 bus vdd. GPIOV1 is connected to
> a 1.8v and a 3.3v power load switch that providing signal voltage to
> SD1 bus.
> If GPIOV0 is active high, SD1 bus is enabled. Otherwise, SD1 bus is
> disabled.
> If GPIOV1 is active high, 3.3v power load switch is enabled, SD1 signal
> voltage is 3.3v. Otherwise, 1.8v power load switch will be enabled, SD1
> signal voltage becomes 1.8v.
>
> AST2600-A2 EVB also support toggling signal voltage for SD2 bus.
> The design is the same as SD1 bus. It uses GPIOV2 as power-gpio and GPIOV3
> as power-switch-gpio.

Thanks for sharing the details, it certainly helps while reviewing.

>
> Signed-off-by: Steven Lee 
> ---
>  .../devicetree/bindings/mmc/aspeed,sdhci.yaml | 25 +++
>  1 file changed, 25 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml 
> b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> index 987b287f3bff..515a74614f3c 100644
> --- a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> +++ b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
> @@ -37,6 +37,14 @@ properties:
>clocks:
>  maxItems: 1
>  description: The SD/SDIO controller clock gate
> +  power-gpio:
> +description:
> +  The GPIO for enabling/disabling SD bus power.
> +maxItems: 1
> +  power-switch-gpio:
> +description:
> +  The GPIO for toggling the signal voltage between 3.3v and 1.8v.
> +maxItems: 1


>
>  patternProperties:
>"^sdhci@[0-9a-f]+$":
> @@ -61,6 +69,14 @@ patternProperties:
>sdhci,auto-cmd12:
>  type: boolean
>  description: Specifies that controller should use auto CMD12
> +  power-gpio:
> +description:
> +  The GPIO for enabling/disabling SD bus power.
> +maxItems: 1
> +  power-switch-gpio:
> +description:
> +  The GPIO for toggling the signal voltage between 3.3v and 1.8v.
> +maxItems: 1
>  required:

Please do not model these as GPIO pins like this. Instead, it's better
to model them as gpio regulators, since the mmc core manages them as
regulators.

We have a vmmc regulator (corresponding to vdd) and a vqmmc regulator
(corresponding the signal-voltage level). These are also described in
the common mmc DT bindings, see
Documentation/devicetree/bindings/mmc/mmc-controller.yaml.

>- compatible
>- reg
> @@ -80,6 +96,7 @@ required:
>  examples:
>- |
>  #include 
> +#include 
>  sdc@1e74 {
>  compatible = "aspeed,ast2500-sd-controller";
>  reg = <0x1e74 0x100>;
> @@ -94,6 +111,10 @@ examples:
>  interrupts = <26>;
>  sdhci,auto-cmd12;
>  clocks = < ASPEED_CLK_SDIO>;
> +power-gpio = < ASPEED_GPIO(V, 0)
> + GPIO_ACTIVE_HIGH>;
> +power-switch-gpio = < ASPEED_GPIO(V, 1)
> + GPIO_ACTIVE_HIGH>;
>  };
>
>  sdhci1: sdhci@200 {
> @@ -102,5 +123,9 @@ examples:
>  interrupts = <26>;
>  sdhci,auto-cmd12;
>  clocks = < ASPEED_CLK_SDIO>;
> +power-gpio = < ASPEED_GPIO(V, 2)
> + GPIO_ACTIVE_HIGH>;
> +power-switch-gpio = < ASPEED_GPIO(V, 3)
> + GPIO_ACTIVE_HIGH>;
>  };
>  };

Kind regards
Uffe


Re: [PATCH v2 1/2] mmc: core: Let sanitize timeout readable/writable via sysfs

2021-04-01 Thread Ulf Hansson
On Thu, 1 Apr 2021 at 15:29, Bean Huo  wrote:
>
> From: Bean Huo 
>
> As the density increases, the 4-minute timeout value for
> sanitize is no longer feasible. At the same time, devices
> of different densities have different timeout values, and it is
> difficult to obtain a unified standard timeout value. Therefore,
> it is better to let the user explicitly change  sanitize timeout
> value according to the eMMC density on the board.

This makes sense. The current timeout in the mmc core isn't good
enough. However, I think there is a better option than inventing a
sysfs node to allow userspace to specify the timeout.

First, we have the card quirks that the mmc core uses to allow us to
modify a common behaviour (in this case timeouts values for sanitize
operations). This can be used to enforce a specific timeout for the
eMMC card. I think this should take precedence over anything else.

Second, the ioctl command allows you to specify a specific command
timeout in the struct mmc_ioc_cmd (.cmd_timeout_ms). If this is
specified from user space we could forward it to mmc_santize() and use
that rather than the default MMC_SANITIZE_TIMEOUT_MS.

Would this satisfy your needs?

Kind regards
Uffe

>
> Signed-off-by: Bean Huo 
> ---
>  drivers/mmc/core/mmc.c | 34 ++
>  drivers/mmc/core/mmc_ops.c |  3 +--
>  include/linux/mmc/card.h   |  1 +
>  3 files changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 8741271d3971..3885cc1780ac 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -28,6 +28,7 @@
>
>  #define DEFAULT_CMD6_TIMEOUT_MS500
>  #define MIN_CACHE_EN_TIMEOUT_MS 1600
> +#define MMC_SANITIZE_TIMEOUT_MS(240 * 1000) /* 240s */
>
>  static const unsigned int tran_exp[] = {
> 1,  10, 100,1000,
> @@ -835,6 +836,37 @@ static ssize_t mmc_dsr_show(struct device *dev,
>
>  static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
>
> +static ssize_t sanitize_timeout_ms_show(struct device *dev,
> +   struct device_attribute *attr,
> +   char *buf)
> +{
> +   struct mmc_card *card = mmc_dev_to_card(dev);
> +
> +   return sysfs_emit(buf, "%d\n", card->sanitize_timeout_ms);
> +}
> +
> +static ssize_t sanitize_timeout_ms_store(struct device *dev,
> +struct device_attribute *attr,
> +const char *buf, size_t len)
> +{
> +   struct mmc_card *card = mmc_dev_to_card(dev);
> +   unsigned int new;
> +   int ret;
> +
> +   ret = kstrtouint(buf, 0, );
> +   if (ret < 0)
> +   return ret;
> +
> +   if (new == 0)
> +   return -EINVAL;
> +
> +   card->sanitize_timeout_ms = new;
> +
> +   return len;
> +}
> +static DEVICE_ATTR_RW(sanitize_timeout_ms);
> +
> +
>  static struct attribute *mmc_std_attrs[] = {
> _attr_cid.attr,
> _attr_csd.attr,
> @@ -861,6 +893,7 @@ static struct attribute *mmc_std_attrs[] = {
> _attr_rca.attr,
> _attr_dsr.attr,
> _attr_cmdq_en.attr,
> +   _attr_sanitize_timeout_ms.attr,
> NULL,
>  };
>  ATTRIBUTE_GROUPS(mmc_std);
> @@ -1623,6 +1656,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> card->ocr = ocr;
> card->type = MMC_TYPE_MMC;
> card->rca = 1;
> +   card->sanitize_timeout_ms = MMC_SANITIZE_TIMEOUT_MS;
> memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
> }
>
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index f413474f0f80..40a4f9e22d30 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -21,7 +21,6 @@
>
>  #define MMC_BKOPS_TIMEOUT_MS   (120 * 1000) /* 120s */
>  #define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
> -#define MMC_SANITIZE_TIMEOUT_MS(240 * 1000) /* 240s */
>
>  static const u8 tuning_blk_pattern_4bit[] = {
> 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
> @@ -1025,7 +1024,7 @@ int mmc_sanitize(struct mmc_card *card)
> mmc_retune_hold(host);
>
> err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START,
> -1, MMC_SANITIZE_TIMEOUT_MS);
> +1, card->sanitize_timeout_ms);
> if (err)
> pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), 
> err);
>
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index f9ad35dd6012..9db0dcd9661e 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -273,6 +273,7 @@ struct mmc_card {
>
> boolreenable_cmdq;  /* Re-enable Command Queue */
>
> +   unsigned intsanitize_timeout_ms;
> unsigned interase_size; /* erase 

Re: [PATCH] mmc: dw_mmc-k3: use the correct HiSilicon copyright

2021-03-31 Thread Ulf Hansson
On Tue, 30 Mar 2021 at 16:27, fanghao (A)  wrote:
>
>
>
> On 2021/3/30 18:38, Ulf Hansson wrote:
> > On Tue, 30 Mar 2021 at 08:43, Hao Fang  wrote:
> >>
> >> s/Hisilicon/HiSilicon/g.
> >> It should use capital S, according to
> >> https://www.hisilicon.com/en/terms-of-use.
> >>
> >> Signed-off-by: Hao Fang 
> >> ---
> >>  drivers/mmc/host/dw_mmc-k3.c | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> >> index 29d2494..0311a37 100644
> >> --- a/drivers/mmc/host/dw_mmc-k3.c
> >> +++ b/drivers/mmc/host/dw_mmc-k3.c
> >> @@ -1,7 +1,7 @@
> >>  // SPDX-License-Identifier: GPL-2.0-or-later
> >>  /*
> >>   * Copyright (c) 2013 Linaro Ltd.
> >> - * Copyright (c) 2013 Hisilicon Limited.
> >> + * Copyright (c) 2013 HiSilicon Limited.
> >
> > This change looks really silly to me, but I am not a lawyer - so I
> > can't tell if this makes sense or not.
> >
> > In any case, "Hisilicon" is being used all over the kernel - do you
> > intend to patch all places with similar changes like this one? Perhaps
> > just send a big tree-wide-patch instead and see what people think?
> >
>
> Although HiSilicon has applied for two trademarks Hisilicon/HiSilicon,
> there is only one English name for the company. We have consulted with
> company's lawyer who suggested that should use a copyright statement
> consistent with the official website.
>
> Though the kernel has tons of "Hisilicon", I just fix the copyright,
> and plan to send a commit to each subsystem where is uncorrect. Fortunately,
> there are not many modules that have the problem, this is one of them.

git grep Hisilicon | grep Copyright | nl
gives 159 cases.

Although if you make one patch per subsystem that should be a lot
less, which seems like a reasonable approach to me.

[...]

So, applied for next, thanks!

Kind regards
Uffe


Re: [PATCH 0/4] mmc: core: Preparations to support SD UHS-II cards

2021-03-31 Thread Ulf Hansson
On Wed, 31 Mar 2021 at 12:26, ReniusChen[陳建宏]
 wrote:
>
> Hi Ulf,
>
>
> I'm currently trying to take over and refactor the task refer to your series.
> And there hasn't been much progress recently because I'm busy with other work.

Alright, thanks for sharing the update.

Don't hesitate to ping me if there is anything you need my help on
around the UHS-II support.

[...]

Kind regards
Uffe


Re: [PATCH 0/4] mmc: core: Preparations to support SD UHS-II cards

2021-03-31 Thread Ulf Hansson
Hi Ben, Renius,

On Thu, 25 Feb 2021 at 18:04, Ulf Hansson  wrote:
>
> A series [1] that has been collaborative worked upon by Takahiro Akashi
> (Linaro) and Ben Chuang (Genesys Logic) is targeting to add SD UHS-II support
> to the mmc subsystem.
>
> Throughout the reviews, we realized that the changes affecting the mmc core to
> support the UHS-II interface/protocol might not be entirely straightforward to
> implement. Especially, I expressed some concerns about the code that manages
> power on/off, initialization and power management of a SD UHS-II card.
>
> Therefore, I have posted this small series to try to help to put some of the
> foundation in the mmc core in place. Hopefully this can provide some guidance
> and an overall structure, of how I think the code could evolve.
>
> More details are available in the commit messages and through comments in the
> code, for each path.
>
> Kind regards
> Uffe

I just wanted to get an update from your side. Did $subject series
help to move things forward?

If there is anything else I can help with, then please ping me.

Kind regards
Uffe

>
> [1]
> https://lkml.org/lkml/2020/11/5/1472
>
>
> Ulf Hansson (4):
>   mmc: core: Cleanup printing of speed mode at card insertion
>   mmc: core: Prepare to support SD UHS-II cards
>   mmc: core: Announce successful insertion of an SD UHS-II card
>   mmc: core: Extend support for mmc regulators with a vqmmc2
>
>  drivers/mmc/core/Makefile|   2 +-
>  drivers/mmc/core/bus.c   |  38 +++--
>  drivers/mmc/core/core.c  |  17 ++-
>  drivers/mmc/core/core.h  |   1 +
>  drivers/mmc/core/host.h  |   5 +
>  drivers/mmc/core/regulator.c |  34 +
>  drivers/mmc/core/sd_uhs2.c   | 289 +++
>  include/linux/mmc/card.h |   6 +
>  include/linux/mmc/host.h |  30 
>  9 files changed, 404 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/mmc/core/sd_uhs2.c
>
> --
> 2.25.1
>


Re: [External] : Re: [PATCH v2] mmc-utils: Add eMMC erase command support

2021-03-31 Thread Ulf Hansson
On Tue, 30 Mar 2021 at 23:36,  wrote:
>
>
>
> On 3/30/2021 6:39 AM, Ulf Hansson wrote:
> > On Wed, 24 Mar 2021 at 17:45, Bean Huo  wrote:
> >> From: Kimito Sakata 
> >>
> >> we have been using this erase feature for a while, but it is
> >> still not merged into the upstream mmc-utils. Especially, for
> >> the customer, every time when they update the mmc-utils, they
> >> should re-install this patch again, let's try to make this
> >> erase command upstreamed in the mmc-utils.
> >>
> >> Co-developed-by: Bean Huo 
> >> Signed-off-by: Bean Huo 
> >> Reviewed-by: Kenneth Gibbons 
> >> ---
> >>
> >> Hi Ulf,
> >> Please help us review this mmc-utils patch, and if agree, it is
> >> possible to make it merged in the official mmc-utils.
> >>
> >> Changelog:
> >>
> >> V1--V2:
> >>  1. refactor Kimito's original patch
> >>  2. change to use MMC_IOC_MULTI_CMD
> >>  3. add checkup if eMMC devie supports secure erase/trim
> >>
> >> ---
> >>   mmc.c  |   8 
> >>   mmc.h  |  13 +-
> >>   mmc_cmds.c | 135 +
> >>   mmc_cmds.h |   1 +
> >>   4 files changed, 156 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/mmc.c b/mmc.c
> >> index 50c9c9e..cb29a65 100644
> >> --- a/mmc.c
> >> +++ b/mmc.c
> >> @@ -215,6 +215,14 @@ static struct Command commands[] = {
> >>  "Run Field Firmware Update with  on 
> >> .\n",
> >>NULL
> >>  },
> >> +   { do_erase, -4,
> >> +   "erase", " " " " " " "\n"
> >> +   "Send Erase CMD38 with specific argument to the 
> >> \n\n"
> >> +   "NOTE!: This will delete all user data in the specified 
> >> region of the device\n"
> >> +   " must be: legacy | discard | secure-erase | "
> >> +   "secure-trim1 | secure-trim2 | trim \n",
> >> +   NULL
> >> +   },
> >>  { 0, 0, 0, 0 }
> >>   };
> >>
> >> diff --git a/mmc.h b/mmc.h
> >> index 648fb26..90b7fb5 100644
> >> --- a/mmc.h
> >> +++ b/mmc.h
> >> @@ -34,7 +34,15 @@
> >>   #define MMC_SET_WRITE_PROT 28/* ac   [31:0] data addr   R1b */
> >>   #define MMC_CLEAR_WRITE_PROT   29/* ac   [31:0] data addr   R1b */
> >>   #define MMC_SEND_WRITE_PROT_TYPE 31   /* ac   [31:0] data addr   R1  */
> >> -
> >> +#define MMC_ERASE_GROUP_START  35/* ac   [31:0] data addr   R1  */
> >> +#define MMC_ERASE_GROUP_END36/* ac   [31:0] data addr   R1  */
> >> +#define MMC_ERASE  38/* ac   [31] Secure request
> >> + [30:16] set to 0
> >> + [15] Force Garbage Collect 
> >> request
> >> + [14:2] set to 0
> >> + [1] Discard Enable
> >> + [0] Identify Write Blocks for
> >> + Erase (or TRIM Enable)  R1b 
> >> */
> >>   /*
> >>* EXT_CSD fields
> >>*/
> >> @@ -61,6 +69,7 @@
> >>   #define EXT_CSD_CACHE_SIZE_2   251
> >>   #define EXT_CSD_CACHE_SIZE_1   250
> >>   #define EXT_CSD_CACHE_SIZE_0   249
> >> +#define EXT_CSD_SEC_FEATURE_SUPPORT231
> >>   #define EXT_CSD_BOOT_INFO  228 /* R/W */
> >>   #define EXT_CSD_HC_ERASE_GRP_SIZE  224
> >>   #define EXT_CSD_HC_WP_GRP_SIZE 221
> >> @@ -177,6 +186,8 @@
> >>   #define EXT_CSD_REV_V4_2   2
> >>   #define EXT_CSD_REV_V4_1   1
> >>   #define EXT_CSD_REV_V4_0   0
> >> +#define EXT_CSD_SEC_GB_CL_EN   (1<<4)
> >> +#define EXT_CSD_SEC_ER_EN  (1<<0)
> >>
> >>
> >>   /* From kernel linux/mmc/core.h */
> >> diff --git a/mmc_cmds.c b/mmc_cmds.c
> >> index fb37189..17986e3 100644
> >> --- a/mmc_cmds.c
> >> +++ b/mmc_cmds.c
> >> @@ -2435,6 +2435,141 @@ int do_cache_dis(int nargs, char **argv)
> >>  return do_cache_ctrl(0, nargs, argv);
> >>   }
> >>
> >> +static int erase(int dev_fd, __u32 argin, __u32 start, __u32 end)
> >> +{
> >> +#ifndef MMC_IOC_MULTI_CMD
> > In kernel v4.4 we added the multi cmd support, which is quite some
> > time ago. So, I think it's time to drop these ifdef hackary from the
> > userland tool. At least, we shouldn't need it for new kinds of
> > features that we add.
> Ulf
> Do you want us to take out the  MMC_IOC_MULTI_CMD ifdef and resubmit?

Yes, please.

Moreover, we should probably also remove all the other #ifndef
MMC_IOC_MULTI_CMD hacks that we currently have in the code. But that's
a separate patch.

> Kimito
>
> >
> >> +   fprintf(stderr, "mmc-utils has been compiled without 
> >> MMC_IOC_MULTI_CMD"
> >> +   " support, needed by erase.\n");
> >> +   return -ENOTSUP;
> >> +#else
> >> +   int ret = 0;
> >> +   struct mmc_ioc_multi_cmd *multi_cmd;
> >> +
> > [...]

Kind regards
Uffe


Re: [PATCH v2] mmc-utils: Add eMMC erase command support

2021-03-30 Thread Ulf Hansson
On Wed, 24 Mar 2021 at 17:45, Bean Huo  wrote:
>
> From: Kimito Sakata 
>
> we have been using this erase feature for a while, but it is
> still not merged into the upstream mmc-utils. Especially, for
> the customer, every time when they update the mmc-utils, they
> should re-install this patch again, let's try to make this
> erase command upstreamed in the mmc-utils.
>
> Co-developed-by: Bean Huo 
> Signed-off-by: Bean Huo 
> Reviewed-by: Kenneth Gibbons 
> ---
>
> Hi Ulf,
> Please help us review this mmc-utils patch, and if agree, it is
> possible to make it merged in the official mmc-utils.
>
> Changelog:
>
> V1--V2:
> 1. refactor Kimito's original patch
> 2. change to use MMC_IOC_MULTI_CMD
> 3. add checkup if eMMC devie supports secure erase/trim
>
> ---
>  mmc.c  |   8 
>  mmc.h  |  13 +-
>  mmc_cmds.c | 135 +
>  mmc_cmds.h |   1 +
>  4 files changed, 156 insertions(+), 1 deletion(-)
>
> diff --git a/mmc.c b/mmc.c
> index 50c9c9e..cb29a65 100644
> --- a/mmc.c
> +++ b/mmc.c
> @@ -215,6 +215,14 @@ static struct Command commands[] = {
> "Run Field Firmware Update with  on .\n",
>   NULL
> },
> +   { do_erase, -4,
> +   "erase", " " " " " " "\n"
> +   "Send Erase CMD38 with specific argument to the \n\n"
> +   "NOTE!: This will delete all user data in the specified 
> region of the device\n"
> +   " must be: legacy | discard | secure-erase | "
> +   "secure-trim1 | secure-trim2 | trim \n",
> +   NULL
> +   },
> { 0, 0, 0, 0 }
>  };
>
> diff --git a/mmc.h b/mmc.h
> index 648fb26..90b7fb5 100644
> --- a/mmc.h
> +++ b/mmc.h
> @@ -34,7 +34,15 @@
>  #define MMC_SET_WRITE_PROT 28/* ac   [31:0] data addr   R1b */
>  #define MMC_CLEAR_WRITE_PROT   29/* ac   [31:0] data addr   R1b */
>  #define MMC_SEND_WRITE_PROT_TYPE 31   /* ac   [31:0] data addr   R1  */
> -
> +#define MMC_ERASE_GROUP_START  35/* ac   [31:0] data addr   R1  */
> +#define MMC_ERASE_GROUP_END36/* ac   [31:0] data addr   R1  */
> +#define MMC_ERASE  38/* ac   [31] Secure request
> + [30:16] set to 0
> + [15] Force Garbage Collect 
> request
> + [14:2] set to 0
> + [1] Discard Enable
> + [0] Identify Write Blocks for
> + Erase (or TRIM Enable)  R1b */
>  /*
>   * EXT_CSD fields
>   */
> @@ -61,6 +69,7 @@
>  #define EXT_CSD_CACHE_SIZE_2   251
>  #define EXT_CSD_CACHE_SIZE_1   250
>  #define EXT_CSD_CACHE_SIZE_0   249
> +#define EXT_CSD_SEC_FEATURE_SUPPORT231
>  #define EXT_CSD_BOOT_INFO  228 /* R/W */
>  #define EXT_CSD_HC_ERASE_GRP_SIZE  224
>  #define EXT_CSD_HC_WP_GRP_SIZE 221
> @@ -177,6 +186,8 @@
>  #define EXT_CSD_REV_V4_2   2
>  #define EXT_CSD_REV_V4_1   1
>  #define EXT_CSD_REV_V4_0   0
> +#define EXT_CSD_SEC_GB_CL_EN   (1<<4)
> +#define EXT_CSD_SEC_ER_EN  (1<<0)
>
>
>  /* From kernel linux/mmc/core.h */
> diff --git a/mmc_cmds.c b/mmc_cmds.c
> index fb37189..17986e3 100644
> --- a/mmc_cmds.c
> +++ b/mmc_cmds.c
> @@ -2435,6 +2435,141 @@ int do_cache_dis(int nargs, char **argv)
> return do_cache_ctrl(0, nargs, argv);
>  }
>
> +static int erase(int dev_fd, __u32 argin, __u32 start, __u32 end)
> +{
> +#ifndef MMC_IOC_MULTI_CMD

In kernel v4.4 we added the multi cmd support, which is quite some
time ago. So, I think it's time to drop these ifdef hackary from the
userland tool. At least, we shouldn't need it for new kinds of
features that we add.

> +   fprintf(stderr, "mmc-utils has been compiled without 
> MMC_IOC_MULTI_CMD"
> +   " support, needed by erase.\n");
> +   return -ENOTSUP;
> +#else
> +   int ret = 0;
> +   struct mmc_ioc_multi_cmd *multi_cmd;
> +

[...]

Kind regards
Uffe


Re: [PATCH] mmc: sdhci-brcmstb: Remove CQE quirk

2021-03-30 Thread Ulf Hansson
On Thu, 25 Mar 2021 at 20:28, Al Cooper  wrote:
>
> Remove the CQHCI_QUIRK_SHORT_TXFR_DESC_SZ quirk because the
> latest chips have this fixed and earlier chips have other
> CQE problems that prevent the feature from being enabled.
>
> Signed-off-by: Al Cooper 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-brcmstb.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c 
> b/drivers/mmc/host/sdhci-brcmstb.c
> index f9780c65ebe9..f24623aac2db 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -199,7 +199,6 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host,
> if (dma64) {
> dev_dbg(mmc_dev(host->mmc), "Using 64 bit DMA\n");
> cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
> -   cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ;
> }
>
> ret = cqhci_init(cq_host, host->mmc, dma64);
>
> base-commit: e138138003eb3b3d06cc91cf2e8c5dec77e2a31e
> --
> 2.17.1
>


Re: [PATCH] mmc: dw_mmc-k3: use the correct HiSilicon copyright

2021-03-30 Thread Ulf Hansson
On Tue, 30 Mar 2021 at 08:43, Hao Fang  wrote:
>
> s/Hisilicon/HiSilicon/g.
> It should use capital S, according to
> https://www.hisilicon.com/en/terms-of-use.
>
> Signed-off-by: Hao Fang 
> ---
>  drivers/mmc/host/dw_mmc-k3.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> index 29d2494..0311a37 100644
> --- a/drivers/mmc/host/dw_mmc-k3.c
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (c) 2013 Linaro Ltd.
> - * Copyright (c) 2013 Hisilicon Limited.
> + * Copyright (c) 2013 HiSilicon Limited.

This change looks really silly to me, but I am not a lawyer - so I
can't tell if this makes sense or not.

In any case, "Hisilicon" is being used all over the kernel - do you
intend to patch all places with similar changes like this one? Perhaps
just send a big tree-wide-patch instead and see what people think?

>   */
>
>  #include 

Kind regards
Uffe


Re: [PATCH v2 05/13] mmc: sdhci-cadence: Add Pensando Elba SoC support

2021-03-30 Thread Ulf Hansson
+ Masahiro Yamada (main author of the driver)

On Mon, 29 Mar 2021 at 03:59, Brad Larson  wrote:
>
> Add support for Pensando Elba SoC which explicitly controls
> byte-lane enables on writes.  Refactor to allow platform
> specific write ops.
>
> Signed-off-by: Brad Larson 
> ---
>  drivers/mmc/host/Kconfig  |  15 +++
>  drivers/mmc/host/Makefile |   1 +
>  drivers/mmc/host/sdhci-cadence-elba.c | 137 ++

By looking at the amount of code changes that seem to be needed to
support the Pensando Elba variant, I don't think it's necessary to
split this into a separate file.

Unless Yamada-san has a different opinion, I would rather just stick
with using sdhci-cadence.c.

>  drivers/mmc/host/sdhci-cadence.c  |  81 ---
>  drivers/mmc/host/sdhci-cadence.h  |  68 +
>  5 files changed, 260 insertions(+), 42 deletions(-)
>  create mode 100644 drivers/mmc/host/sdhci-cadence-elba.c
>  create mode 100644 drivers/mmc/host/sdhci-cadence.h
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index b236dfe2e879..65ea323c06f2 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -250,6 +250,21 @@ config MMC_SDHCI_CADENCE
>
>   If unsure, say N.
>
> +config MMC_SDHCI_CADENCE_ELBA
> +   tristate "SDHCI support for the Pensando/Cadence SD/SDIO/eMMC 
> controller"
> +   depends on ARCH_PENSANDO_ELBA_SOC
> +   depends on MMC_SDHCI
> +   depends on OF
> +   depends on MMC_SDHCI_CADENCE
> +   depends on MMC_SDHCI_PLTFM
> +   select MMC_SDHCI_IO_ACCESSORS

According to the comment above - then you should probably just extend
the conditions for when building MMC_SDHCI_CADENCE, rather than having
to add a new Kconfig for "*_ELBA".

> +   help
> + This selects the Pensando/Cadence SD/SDIO/eMMC controller.
> +
> + If you have a controller with this interface, say Y or M here.
> +
> + If unsure, say N.
> +
>  config MMC_SDHCI_CNS3XXX
> tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
> depends on ARCH_CNS3XXX || COMPILE_TEST
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 6df5c4774260..f2a6d50e64de 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -80,6 +80,7 @@ obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o
>
>  obj-$(CONFIG_MMC_SDHCI_PLTFM)  += sdhci-pltfm.o
>  obj-$(CONFIG_MMC_SDHCI_CADENCE)+= sdhci-cadence.o
> +obj-$(CONFIG_MMC_SDHCI_CADENCE_ELBA)   += sdhci-cadence-elba.o
>  obj-$(CONFIG_MMC_SDHCI_CNS3XXX)+= sdhci-cns3xxx.o
>  obj-$(CONFIG_MMC_SDHCI_ESDHC_MCF)   += sdhci-esdhc-mcf.o
>  obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)  += sdhci-esdhc-imx.o
> diff --git a/drivers/mmc/host/sdhci-cadence-elba.c 
> b/drivers/mmc/host/sdhci-cadence-elba.c
> new file mode 100644
> index ..ec23f43de407
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-cadence-elba.c
> @@ -0,0 +1,137 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2020 Pensando Systems, Inc.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "sdhci-pltfm.h"
> +#include "sdhci-cadence.h"
> +
> +// delay regs address

Please don't use "//" when adding comments, but instead "/* ... */".
This applies to several more places of the patch.

> +#define SDIO_REG_HRS4  0x10
> +#define REG_DELAY_HS   0x00
> +#define REG_DELAY_DEFAULT  0x01
> +#define REG_DELAY_UHSI_SDR50   0x04
> +#define REG_DELAY_UHSI_DDR50   0x05
> +
> +static void elba_write_l(struct sdhci_host *host, u32 val, int reg)
> +{
> +   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(>wrlock, flags);
> +   writel(0x78, priv->ctl_addr);
> +   writel(val, host->ioaddr + reg);
> +   spin_unlock_irqrestore(>wrlock, flags);
> +}
> +
> +static void elba_write_w(struct sdhci_host *host, u16 val, int reg)
> +{
> +   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
> +   unsigned long flags;
> +   u32 m = (reg & 0x3);
> +   u32 msk = (0x3 << (m));
> +
> +   spin_lock_irqsave(>wrlock, flags);
> +   writel(msk << 3, priv->ctl_addr);
> +   writew(val, host->ioaddr + reg);
> +   spin_unlock_irqrestore(>wrlock, flags);
> +}
> +
> +static void elba_write_b(struct sdhci_host *host, u8 val, int reg)
> +{
> +   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
> +   unsigned long flags;
> +   u32 m = (reg & 0x3);
> +   u32 msk = (0x1 << (m));
> +
> +   spin_lock_irqsave(>wrlock, flags);
> +   writel(msk << 3, priv->ctl_addr);
> +   writeb(val, host->ioaddr + reg);
> +   spin_unlock_irqrestore(>wrlock, flags);
> +}
> +
> +static void elba_priv_write_l(struct sdhci_cdns_priv *priv,
> +   u32 val, void __iomem *reg)
> +{
> +   unsigned 

Re: [PATCH] mmc: sdhci: replace mmc->parent with mmc_dev() for consistency

2021-03-24 Thread Ulf Hansson
On Wed, 24 Mar 2021 at 08:50, Jisheng Zhang  wrote:
>
> As pointed out by Ulf, "both "mmc->parent" and mmc_dev(mmc) are being
> used in the entire c-file". Convert all the mmc->parent usage in all
> sdhci host driver to mmc_dev() for consistency.
>
> Suggested-by: Ulf Hansson 
> Signed-off-by: Jisheng Zhang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-esdhc-mcf.c |  8 +++
>  drivers/mmc/host/sdhci-of-aspeed.c |  2 +-
>  drivers/mmc/host/sdhci-tegra.c | 34 +++---
>  drivers/mmc/host/sdhci.c   | 24 ++---
>  drivers/mmc/host/sdhci_am654.c |  2 +-
>  5 files changed, 35 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c 
> b/drivers/mmc/host/sdhci-esdhc-mcf.c
> index ca7a1690b2a8..05926bf5ecf9 100644
> --- a/drivers/mmc/host/sdhci-esdhc-mcf.c
> +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c
> @@ -367,14 +367,14 @@ static int esdhc_mcf_plat_init(struct sdhci_host *host,
>struct pltfm_mcf_data *mcf_data)
>  {
> struct mcf_esdhc_platform_data *plat_data;
> +   struct device *dev = mmc_dev(host->mmc);
>
> -   if (!host->mmc->parent->platform_data) {
> -   dev_err(mmc_dev(host->mmc), "no platform data!\n");
> +   if (!dev->platform_data) {
> +   dev_err(dev, "no platform data!\n");
> return -EINVAL;
> }
>
> -   plat_data = (struct mcf_esdhc_platform_data *)
> -   host->mmc->parent->platform_data;
> +   plat_data = (struct mcf_esdhc_platform_data *)dev->platform_data;
>
> /* Card_detect */
> switch (plat_data->cd_type) {
> diff --git a/drivers/mmc/host/sdhci-of-aspeed.c 
> b/drivers/mmc/host/sdhci-of-aspeed.c
> index 7d8692e90996..d001c51074a0 100644
> --- a/drivers/mmc/host/sdhci-of-aspeed.c
> +++ b/drivers/mmc/host/sdhci-of-aspeed.c
> @@ -181,7 +181,7 @@ aspeed_sdhci_configure_phase(struct sdhci_host *host, 
> unsigned long rate)
> struct aspeed_sdhci *sdhci;
> struct device *dev;
>
> -   dev = host->mmc->parent;
> +   dev = mmc_dev(host->mmc);
> sdhci = sdhci_pltfm_priv(sdhci_priv(host));
>
> if (!sdhci->phase_desc)
> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
> index 41d193fa77bb..c61f797a853f 100644
> --- a/drivers/mmc/host/sdhci-tegra.c
> +++ b/drivers/mmc/host/sdhci-tegra.c
> @@ -596,49 +596,49 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct 
> sdhci_host *host)
> _host->autocal_offsets;
> int err;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-up-offset-3v3",
> >pull_up_3v3);
> if (err)
> autocal->pull_up_3v3 = 0;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-down-offset-3v3",
> >pull_down_3v3);
> if (err)
> autocal->pull_down_3v3 = 0;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-up-offset-1v8",
> >pull_up_1v8);
> if (err)
> autocal->pull_up_1v8 = 0;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-down-offset-1v8",
> >pull_down_1v8);
> if (err)
> autocal->pull_down_1v8 = 0;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-up-offset-sdr104",
> >pull_up_sdr104);
> if (err)
> autocal->pull_up_sdr104 = autocal->pull_up_1v8;
>
> -   err = device_property_read_u32(host->mmc->parent,
> +   err = device_property_read_u32(mmc_dev(host->mmc),
> "nvidia,pad-autocal-pull-down-offset-sdr104",
> >pull_down_sdr104);
> if (err)
> autoca

Re: [PATCH] mmc: sdhci-of-dwcmshc: set MMC_CAP_WAIT_WHILE_BUSY

2021-03-24 Thread Ulf Hansson
On Wed, 24 Mar 2021 at 08:47, Jisheng Zhang  wrote:
>
> The host supports HW busy detection of the device busy signaling over
> dat0 line. Set MMC_CAP_wAIT_WHILE_BUSY host capability.
>
> Signed-off-by: Jisheng Zhang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c 
> b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 06873686d5e9..b6ceb1b92b3f 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> @@ -393,6 +393,8 @@ static int dwcmshc_probe(struct platform_device *pdev)
> goto err_clk;
> }
>
> +   host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
> +
> err = sdhci_add_host(host);
> if (err)
> goto err_clk;
> --
> 2.31.0
>


Re: [PATCH v3] mmc: sdhci-of-dwcmshc: add ACPI support for BlueField-3 SoC

2021-03-24 Thread Ulf Hansson
On Mon, 22 Mar 2021 at 23:47, Liming Sun  wrote:
>
> This commit adds ACPI support in the sdhci-of-dwcmshc driver for
> BlueField-3 SoC. It has changes to only use the clock hierarchy
> for Deviec Tree since the clk is not supported by ACPI. Instead,
> ACPI can define 'clock-frequency' which is parsed by existing
> sdhci_get_property(). This clock value will be returned in function
> dwcmshc_get_max_clock().
>
> Signed-off-by: Liming Sun 
> Reviewed-by: Khalil Blaiech 

Applied for next, thanks!

Kind regards
Uffe


> ---
> v2->v3:
>Rebase to mmc next.
> v1->v2:
>Changes for comments from Adrian Hunter :
>- Make changes in sdhci-of-dwcmshc instead.
> v1: Initial version which was done in sdhci-acpi.c
> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 50 
> ++---
>  1 file changed, 36 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c 
> b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 0687368..1113a56 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> @@ -7,6 +7,7 @@
>   * Author: Jisheng Zhang 
>   */
>
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -94,6 +95,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host 
> *host, void **desc,
> sdhci_adma_write_desc(host, desc, addr, len, cmd);
>  }
>
> +static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
> +{
> +   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +
> +   if (pltfm_host->clk)
> +   return sdhci_pltfm_clk_get_max_clock(host);
> +   else
> +   return pltfm_host->clock;
> +}
> +
>  static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
>  struct mmc_request *mrq)
>  {
> @@ -248,7 +259,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host 
> *host, unsigned int clock
> .set_clock  = sdhci_set_clock,
> .set_bus_width  = sdhci_set_bus_width,
> .set_uhs_signaling  = dwcmshc_set_uhs_signaling,
> -   .get_max_clock  = sdhci_pltfm_clk_get_max_clock,
> +   .get_max_clock  = dwcmshc_get_max_clock,
> .reset  = sdhci_reset,
> .adma_write_desc= dwcmshc_adma_write_desc,
>  };
> @@ -323,8 +334,16 @@ static int dwcmshc_rk3568_init(struct sdhci_host *host, 
> struct dwcmshc_priv *dwc
>  };
>  MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
>
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = {
> +   { .id = "MLNXBF30" },
> +   {}
> +};
> +#endif
> +
>  static int dwcmshc_probe(struct platform_device *pdev)
>  {
> +   struct device *dev = >dev;
> struct sdhci_pltfm_host *pltfm_host;
> struct sdhci_host *host;
> struct dwcmshc_priv *priv;
> @@ -347,7 +366,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
> /*
>  * extra adma table cnt for cross 128M boundary handling.
>  */
> -   extra = DIV_ROUND_UP_ULL(dma_get_required_mask(>dev), SZ_128M);
> +   extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);
> if (extra > SDHCI_MAX_SEGS)
> extra = SDHCI_MAX_SEGS;
> host->adma_table_cnt += extra;
> @@ -355,19 +374,21 @@ static int dwcmshc_probe(struct platform_device *pdev)
> pltfm_host = sdhci_priv(host);
> priv = sdhci_pltfm_priv(pltfm_host);
>
> -   pltfm_host->clk = devm_clk_get(>dev, "core");
> -   if (IS_ERR(pltfm_host->clk)) {
> -   err = PTR_ERR(pltfm_host->clk);
> -   dev_err(>dev, "failed to get core clk: %d\n", err);
> -   goto free_pltfm;
> -   }
> -   err = clk_prepare_enable(pltfm_host->clk);
> -   if (err)
> -   goto free_pltfm;
> +   if (dev->of_node) {
> +   pltfm_host->clk = devm_clk_get(dev, "core");
> +   if (IS_ERR(pltfm_host->clk)) {
> +   err = PTR_ERR(pltfm_host->clk);
> +   dev_err(dev, "failed to get core clk: %d\n", err);
> +   goto free_pltfm;
> +   }
> +   err = clk_prepare_enable(pltfm_host->clk);
> +   if (err)
> +   goto free_pltfm;
>
> -   priv->bus_clk = devm_clk_get(>dev, "bus");
> -   if (!IS_ERR(priv->bus_clk))
> -   clk_prepare_enable(priv->bus_clk);
> +   priv->bus_clk = devm_clk_get(dev, "bus");
> +   if (!IS_ERR(priv->bus_clk))
> +   clk_prepare_enable(priv->bus_clk);
> +   }
>
> err = mmc_of_parse(host->mmc);
> if (err)
> @@ -489,6 +510,7 @@ static int dwcmshc_resume(struct device *dev)
> .name   = "sdhci-dwcmshc",
> .probe_type = PROBE_PREFER_ASYNCHRONOUS,
> .of_match_table = sdhci_dwcmshc_dt_ids,
> +   .acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids),
>

Re: [PATCH v5 08/24] wfx: add bus_sdio.c

2021-03-23 Thread Ulf Hansson
On Tue, 23 Mar 2021 at 18:53, Jérôme Pouiller
 wrote:
>
> On Tuesday 23 March 2021 15:11:56 CET Ulf Hansson wrote:
> > On Mon, 22 Mar 2021 at 18:14, Jérôme Pouiller  
> > wrote:
> > > On Monday 22 March 2021 13:20:35 CET Ulf Hansson wrote:
> > > > On Mon, 15 Mar 2021 at 14:25, Jerome Pouiller 
> > > >  wrote:
> > > > >
> > > > > From: Jérôme Pouiller 
> > > > >
> > > > > Signed-off-by: Jérôme Pouiller 
> > > > > ---
> > > > >  drivers/net/wireless/silabs/wfx/bus_sdio.c | 259 
> > > > > +
> > > > >  1 file changed, 259 insertions(+)
> > > > >  create mode 100644 drivers/net/wireless/silabs/wfx/bus_sdio.c
> > > >
> > > > [...]
> > > >
> > > > > +static const struct sdio_device_id wfx_sdio_ids[] = {
> > > > > +   { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, 
> > > > > SDIO_DEVICE_ID_SILABS_WF200) },
> > > > > +   { },
> > > > > +};
> > > > > +MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
> > > > > +
> > > > > +struct sdio_driver wfx_sdio_driver = {
> > > > > +   .name = "wfx-sdio",
> > > > > +   .id_table = wfx_sdio_ids,
> > > > > +   .probe = wfx_sdio_probe,
> > > > > +   .remove = wfx_sdio_remove,
> > > > > +   .drv = {
> > > > > +   .owner = THIS_MODULE,
> > > > > +   .of_match_table = wfx_sdio_of_match,
> > > >
> > > > It's not mandatory to support power management, like system
> > > > suspend/resume. However, as this looks like this is a driver for an
> > > > embedded SDIO device, you probably want this.
> > > >
> > > > If that is the case, please assign the dev_pm_ops here and implement
> > > > the ->suspend|resume() callbacks.
> > >
> > > I have no platform to test suspend/resume, so I have only a
> > > theoretical understanding of this subject.
> >
> > I see.
> >
> > >
> > > I understanding is that with the current implementation, the
> > > device will be powered off on suspend and then totally reset
> > > (including reloading of the firmware) on resume. I am wrong?
> >
> > You are correct, for a *removable* SDIO card. In this case, the
> > mmc/sdio core will remove the corresponding SDIO card/device and its
> > corresponding SDIO func devices at system suspend. It will then be
> > redetected at system resume (and the SDIO func driver re-probed).
> >
> > Although, as this is an embedded SDIO device, per definition it's not
> > a removable card (MMC_CAP_NONREMOVABLE should be set for the
> > corresponding mmc host), the SDIO card will stick around and instead
> > the ->suspend|resume() callback needs to be implemented for the SDIO
> > func driver.
>
> If I follow what has been done in other drivers I would write something
> like:
>
>   static int wfx_sdio_suspend(struct device *dev)
>   {
>   struct sdio_func *func = dev_to_sdio_func(dev);
>   struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
>
>   config_reg_write_bits(bus->core, CFG_IRQ_ENABLE_DATA, 0);
>   // Necessary to keep device firmware in RAM
>   return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);

This will tell the mmc/sdio core to keep the SDIO card powered on
during system suspend. Thus, it doesn't need to re-initialize it at
system resume - and the firmware should not need to be re-programmed.

On the other hand, if you don't plan to support system wakeups, it
would probably be better to power off the card, to avoid wasting
energy while the system is suspended. I assume that means you need to
re-program the firmware as well. Normally, it's these kinds of things
that need to be managed from a ->resume() callback.

>   }
>
> However, why not the implementation below?
>
>   static int wfx_sdio_suspend(struct device *dev)
>   {
>   struct sdio_func *func = dev_to_sdio_func(dev);
>
>   wfx_sdio_remove(func);

I don't know what wfx_sdio_remove() does, but for sure you would need
a ->resume() callback to make it possible to restore power/firmware.

>   return 0;
>   }
>
> In both cases, I worry to provide these functions without being able to
> test them.

Alright, let's simply leave this driver without having the PM
callbacks assigned. I guess we can revisit this at some later point.

The mmc core will log a message about the missing callbacks, in case
someone tries to execute system suspend/resume when the driver has
been probed.

Kind regards
Uffe


Re: [PATCH v5 08/24] wfx: add bus_sdio.c

2021-03-23 Thread Ulf Hansson
On Mon, 22 Mar 2021 at 18:14, Jérôme Pouiller
 wrote:
>
> Hello Ulf,
>
> On Monday 22 March 2021 13:20:35 CET Ulf Hansson wrote:
> > On Mon, 15 Mar 2021 at 14:25, Jerome Pouiller
> >  wrote:
> > >
> > > From: Jérôme Pouiller 
> > >
> > > Signed-off-by: Jérôme Pouiller 
> > > ---
> > >  drivers/net/wireless/silabs/wfx/bus_sdio.c | 259 +
> > >  1 file changed, 259 insertions(+)
> > >  create mode 100644 drivers/net/wireless/silabs/wfx/bus_sdio.c
> >
> > [...]
> >
> > > +static const struct sdio_device_id wfx_sdio_ids[] = {
> > > +   { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) 
> > > },
> > > +   { },
> > > +};
> > > +MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
> > > +
> > > +struct sdio_driver wfx_sdio_driver = {
> > > +   .name = "wfx-sdio",
> > > +   .id_table = wfx_sdio_ids,
> > > +   .probe = wfx_sdio_probe,
> > > +   .remove = wfx_sdio_remove,
> > > +   .drv = {
> > > +   .owner = THIS_MODULE,
> > > +   .of_match_table = wfx_sdio_of_match,
> >
> > It's not mandatory to support power management, like system
> > suspend/resume. However, as this looks like this is a driver for an
> > embedded SDIO device, you probably want this.
> >
> > If that is the case, please assign the dev_pm_ops here and implement
> > the ->suspend|resume() callbacks.
>
> I have no platform to test suspend/resume, so I have only a
> theoretical understanding of this subject.

I see.

>
> I understanding is that with the current implementation, the
> device will be powered off on suspend and then totally reset
> (including reloading of the firmware) on resume. I am wrong?

You are correct, for a *removable* SDIO card. In this case, the
mmc/sdio core will remove the corresponding SDIO card/device and its
corresponding SDIO func devices at system suspend. It will then be
redetected at system resume (and the SDIO func driver re-probed).

Although, as this is an embedded SDIO device, per definition it's not
a removable card (MMC_CAP_NONREMOVABLE should be set for the
corresponding mmc host), the SDIO card will stick around and instead
the ->suspend|resume() callback needs to be implemented for the SDIO
func driver.

>
> This behavior sounds correct to me. You would expect something
> more?

Yes, see above.

Kind regards
Uffe


Re: [PATCH] mmc: core: Mark mmc_host device with pm_runtime_no_callbacks

2021-03-23 Thread Ulf Hansson
On Tue, 23 Mar 2021 at 11:49, hieagle  wrote:
>
> We encounter a resume issue in our device sometimes. The mmc device's
> parent list is
> mmc0:0001->mmc_host mmc0->fa63.mmc->soc in our soc. We found in the blow
> case with mmc0->power.disable_depth=0 the mmc_runtime_resume will be skipped,
> which cause subsequent mmc command fail.
>
> mmc_get_card(mmc0:0001)->pm_runtime_get_sync->rpm_resume(mmc0:0001)->rpm_resume(mmc0)
> The rpm_resume(mmc0) return -ENOSYS due to no callback and
> mmc0->power.runtime_status
> keep RPM_SUSPENDED. This lead to rpm_resume(mmc0:0001) return -EBUSY and skip
> rpm_callback which call mmc_runtime_resume, the mmc is still in
> suspended and the
> subsequent mmc command fail.
>
> [  198.856157] Call trace:
> [  198.858917] [] dump_backtrace+0x0/0x1cc
> [  198.864966] [] show_stack+0x14/0x1c
> [  198.870627] [] dump_stack+0xa8/0xe0
> [  198.876288] [] rpm_resume+0x850/0x938
> [  198.882141] [] rpm_resume+0x250/0x938
> [  198.887994] [] __pm_runtime_resume+0x50/0x74
> [  198.894530] [] mmc_get_card+0x3c/0xb8
> [  198.900388] [] mmc_blk_issue_rq+0x2b0/0x4d8
> [  198.906824] [] mmc_queue_thread+0xdc/0x198
> [  198.913165] [] kthread+0xec/0x100
> [  198.918632] [] ret_from_fork+0x10/0x40
> [  198.924582] mmc0  callback   (null)
> [  198.935837] mmcblk mmc0:0001: __pm_runtime_resume ret -16
>
> Mark mmc_host device with pm_runtime_no_callbacks will solve the issue.
> Thanks.
> Huanlin Ke

Thanks for sharing more details! I have to admit, that this sounds
quite weird to me. I wonder if this is a problem that deserves to be
fixed in the runtime PM core

Let me have a closer look a get back to you again. Please be patient
though, I have a busy week in front of me.

Kind regards
Uffe

>
> Ulf Hansson  于2021年3月22日周一 下午6:26写道:
> >
> > On Sat, 20 Mar 2021 at 05:57, kehuanlin  wrote:
> > >
> > > The rpm_resume() will call parent's resume callback recursively.
> > > Since mmc_host has no its own pm_runtime callbacks, the mmc devices
> > > may fail to resume (-ENOSYS in rpm_callback) sometimes. Mark mmc_host
> > > device with pm_runtime_no_callbacks can fix the issue.
> >
> > Can you please elaborate more on this? What do you mean by "sometimes"?
> >
> > More precisely, how do you trigger the rpm_callback() for mmc class
> > device to return -ENOSYS?
> >
> > Don't get me wrong, the patch is fine, but I want to understand if it
> > actually solves a problem for you - or that it's better considered as
> > an optimization?
> >
> > Kind regards
> > Uffe
> >
> > >
> > > Signed-off-by: kehuanlin 
> > > ---
> > >  drivers/mmc/core/host.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> > > index 9b89a91b6b47..177bebd9a6c4 100644
> > > --- a/drivers/mmc/core/host.c
> > > +++ b/drivers/mmc/core/host.c
> > > @@ -15,6 +15,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >  #include 
> > >  #include 
> > >  #include 
> > > @@ -480,6 +481,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct 
> > > device *dev)
> > > host->class_dev.class = _host_class;
> > > device_initialize(>class_dev);
> > > device_enable_async_suspend(>class_dev);
> > > +   pm_runtime_no_callbacks(>class_dev);
> > >
> > > if (mmc_gpio_alloc(host)) {
> > > put_device(>class_dev);
> > > --
> > > 2.30.0
> > >


Re: [PATCH v5 08/24] wfx: add bus_sdio.c

2021-03-22 Thread Ulf Hansson
On Mon, 15 Mar 2021 at 14:25, Jerome Pouiller
 wrote:
>
> From: Jérôme Pouiller 
>
> Signed-off-by: Jérôme Pouiller 
> ---
>  drivers/net/wireless/silabs/wfx/bus_sdio.c | 259 +
>  1 file changed, 259 insertions(+)
>  create mode 100644 drivers/net/wireless/silabs/wfx/bus_sdio.c

[...]

> +static const struct sdio_device_id wfx_sdio_ids[] = {
> +   { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) },
> +   { },
> +};
> +MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
> +
> +struct sdio_driver wfx_sdio_driver = {
> +   .name = "wfx-sdio",
> +   .id_table = wfx_sdio_ids,
> +   .probe = wfx_sdio_probe,
> +   .remove = wfx_sdio_remove,
> +   .drv = {
> +   .owner = THIS_MODULE,
> +   .of_match_table = wfx_sdio_of_match,

It's not mandatory to support power management, like system
suspend/resume. However, as this looks like this is a driver for an
embedded SDIO device, you probably want this.

If that is the case, please assign the dev_pm_ops here and implement
the ->suspend|resume() callbacks.

[...]

Kind regards
Uffe


Re: [PATCH] mmc: core: Mark mmc_host device with pm_runtime_no_callbacks

2021-03-22 Thread Ulf Hansson
On Sat, 20 Mar 2021 at 05:57, kehuanlin  wrote:
>
> The rpm_resume() will call parent's resume callback recursively.
> Since mmc_host has no its own pm_runtime callbacks, the mmc devices
> may fail to resume (-ENOSYS in rpm_callback) sometimes. Mark mmc_host
> device with pm_runtime_no_callbacks can fix the issue.

Can you please elaborate more on this? What do you mean by "sometimes"?

More precisely, how do you trigger the rpm_callback() for mmc class
device to return -ENOSYS?

Don't get me wrong, the patch is fine, but I want to understand if it
actually solves a problem for you - or that it's better considered as
an optimization?

Kind regards
Uffe

>
> Signed-off-by: kehuanlin 
> ---
>  drivers/mmc/core/host.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 9b89a91b6b47..177bebd9a6c4 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -15,6 +15,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -480,6 +481,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device 
> *dev)
> host->class_dev.class = _host_class;
> device_initialize(>class_dev);
> device_enable_async_suspend(>class_dev);
> +   pm_runtime_no_callbacks(>class_dev);
>
> if (mmc_gpio_alloc(host)) {
> put_device(>class_dev);
> --
> 2.30.0
>


Re: [PATCH v2] mmc: sdhci-of-dwcmshc: add ACPI support for BlueField-3 SoC

2021-03-22 Thread Ulf Hansson
On Fri, 19 Mar 2021 at 21:23, Liming Sun  wrote:
>
> Uffe,
>
> Can I confirm whether you meant the 'master' branch or some other branch?
> I did a rebase of master and didn't see Shawn Lin's changes in the 
> sdhci-of-dwcmshc.c

git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git next

[...]

Kind regards
Uffe


Re: [PATCH v2] mmc: sdhci-of-dwcmshc: add ACPI support for BlueField-3 SoC

2021-03-19 Thread Ulf Hansson
On Wed, 17 Mar 2021 at 00:20, Liming Sun  wrote:
>
> This commit adds ACPI support in the sdhci-of-dwcmshc driver for
> BlueField-3 SoC. It has changes to only use the clock hierarchy
> for Deviec Tree since the clk is not supported by ACPI. Instead,
> ACPI can define 'clock-frequency' which is parsed by existing
> sdhci_get_property(). This clock value will be returned in function
> dwcmshc_get_max_clock().
>
> Signed-off-by: Liming Sun 
> Reviewed-by: Khalil Blaiech 

Liming, can you please rebase and repost a new version. It seems like
Shawn Lin's patch that added rockchip platform support causes the
conflict.

Kind regards
Uffe


> ---
> v1->v2:
>Changes for comments from Adrian Hunter :
>- Make changes in sdhci-of-dwcmshc instead.
> v1: Initial version which was done in sdhci-acpi.c
> ---
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 50 
> ++---
>  1 file changed, 36 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c 
> b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 59d8d96..bf5037a 100644
> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
> @@ -7,6 +7,7 @@
>   * Author: Jisheng Zhang 
>   */
>
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -51,6 +52,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host 
> *host, void **desc,
> sdhci_adma_write_desc(host, desc, addr, len, cmd);
>  }
>
> +static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
> +{
> +   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +
> +   if (pltfm_host->clk)
> +   return sdhci_pltfm_clk_get_max_clock(host);
> +   else
> +   return pltfm_host->clock;
> +}
> +
>  static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
>  struct mmc_request *mrq)
>  {
> @@ -104,7 +115,7 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host 
> *host,
> .set_clock  = sdhci_set_clock,
> .set_bus_width  = sdhci_set_bus_width,
> .set_uhs_signaling  = dwcmshc_set_uhs_signaling,
> -   .get_max_clock  = sdhci_pltfm_clk_get_max_clock,
> +   .get_max_clock  = dwcmshc_get_max_clock,
> .reset  = sdhci_reset,
> .adma_write_desc= dwcmshc_adma_write_desc,
>  };
> @@ -117,6 +128,7 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host 
> *host,
>
>  static int dwcmshc_probe(struct platform_device *pdev)
>  {
> +   struct device *dev = >dev;
> struct sdhci_pltfm_host *pltfm_host;
> struct sdhci_host *host;
> struct dwcmshc_priv *priv;
> @@ -131,7 +143,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
> /*
>  * extra adma table cnt for cross 128M boundary handling.
>  */
> -   extra = DIV_ROUND_UP_ULL(dma_get_required_mask(>dev), SZ_128M);
> +   extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);
> if (extra > SDHCI_MAX_SEGS)
> extra = SDHCI_MAX_SEGS;
> host->adma_table_cnt += extra;
> @@ -139,19 +151,21 @@ static int dwcmshc_probe(struct platform_device *pdev)
> pltfm_host = sdhci_priv(host);
> priv = sdhci_pltfm_priv(pltfm_host);
>
> -   pltfm_host->clk = devm_clk_get(>dev, "core");
> -   if (IS_ERR(pltfm_host->clk)) {
> -   err = PTR_ERR(pltfm_host->clk);
> -   dev_err(>dev, "failed to get core clk: %d\n", err);
> -   goto free_pltfm;
> +   if (dev->of_node) {
> +   pltfm_host->clk = devm_clk_get(dev, "core");
> +   if (IS_ERR(pltfm_host->clk)) {
> +   err = PTR_ERR(pltfm_host->clk);
> +   dev_err(dev, "failed to get core clk: %d\n", err);
> +   goto free_pltfm;
> +   }
> +   err = clk_prepare_enable(pltfm_host->clk);
> +   if (err)
> +   goto free_pltfm;
> +
> +   priv->bus_clk = devm_clk_get(dev, "bus");
> +   if (!IS_ERR(priv->bus_clk))
> +   clk_prepare_enable(priv->bus_clk);
> }
> -   err = clk_prepare_enable(pltfm_host->clk);
> -   if (err)
> -   goto free_pltfm;
> -
> -   priv->bus_clk = devm_clk_get(>dev, "bus");
> -   if (!IS_ERR(priv->bus_clk))
> -   clk_prepare_enable(priv->bus_clk);
>
> err = mmc_of_parse(host->mmc);
> if (err)
> @@ -239,11 +253,19 @@ static int dwcmshc_resume(struct device *dev)
>  };
>  MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
>
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = {
> +   { .id = "MLNXBF30" },
> +   {}
> +};
> +#endif
> +
>  static struct platform_driver sdhci_dwcmshc_driver = {
> .driver = {
> .name   = "sdhci-dwcmshc",
> .probe_type = PROBE_PREFER_ASYNCHRONOUS,
>

Re: [PATCH v2 4/8] dt-bindings: mmc: Add compatible for Mediatek MT8195

2021-03-19 Thread Ulf Hansson
On Fri, 19 Mar 2021 at 03:36, Seiya Wang  wrote:
>
> This commit adds dt-binding documentation of mmc for Mediatek MT8195 SoC
> Platform.
>
> Signed-off-by: Seiya Wang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml 
> b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> index 01630b0ecea7..8648d48dbbfd 100644
> --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
> @@ -31,6 +31,7 @@ properties:
>- const: mediatek,mt2701-mmc
>- items:
>- const: mediatek,mt8192-mmc
> +  - const: mediatek,mt8195-mmc
>- const: mediatek,mt8183-mmc
>
>clocks:
> --
> 2.14.1
>


Re: [PATCH v1 1/2] mmc: cavium: Use '"%s...", __func__' to print function name

2021-03-19 Thread Ulf Hansson
On Fri, 19 Mar 2021 at 13:14, Bean Huo  wrote:
>
> From: Bean Huo 
>
> Use preferred way '"%s...", __func__' to print function name.
>
> Signed-off-by: Bean Huo 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/cavium.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
> index 4bb8f2800a2b..95a41983c6c0 100644
> --- a/drivers/mmc/host/cavium.c
> +++ b/drivers/mmc/host/cavium.c
> @@ -656,8 +656,7 @@ static void cvm_mmc_dma_request(struct mmc_host *mmc,
>
> if (!mrq->data || !mrq->data->sg || !mrq->data->sg_len ||
> !mrq->stop || mrq->stop->opcode != MMC_STOP_TRANSMISSION) {
> -   dev_err(>card->dev,
> -   "Error: cmv_mmc_dma_request no data\n");
> +   dev_err(>card->dev, "Error: %s no data\n", __func__);
> goto error;
> }
>
> --
> 2.25.1
>


Re: [PATCH v1 2/2] mmc: cavium: Remove redundant if-statement checkup

2021-03-19 Thread Ulf Hansson
On Fri, 19 Mar 2021 at 13:14, Bean Huo  wrote:
>
> From: Bean Huo 
>
> Currently, we have two ways to issue multiple-block read/write the
> command to the eMMC. One is by normal IO request path fs->block->mmc.
> Another one is that we can issue multiple-block read/write through
> MMC ioctl interface. For the first path, mrq->stop, and mrq->stop->opcode
> will be initialized in mmc_blk_data_prep(). However, for the second IO
> path, mrq->stop is not initialized since it is a pre-defined multiple
> blocks read/write.

As a matter of fact this way is also supported for the regular block
I/O path. To make the mmc block driver to use it, mmc host drivers
need to announce that it's supported by setting MMC_CAP_CMD23.

It looks like that is what your patch should be targeted towards, can
you have a look at this instead?

Kind regards
Uffe

>
> Meanwhile, if it is open-ended multiple block read/write command,
> STOP_TRANSMISSION CMD12 will be issued later in mmc_blk_issue_drv_op(),
> since it is MMC_IOC_MULTI_CMD.
>
> So, delete these if-statement checkups, let these kinds of multiple-block
> read/write request go.
>
> Fixes 'ba3869ff32e4 ("mmc: cavium: Add core MMC driver for Cavium SOCs")'
> Cc: sta...@vger.kernel.org
> Signed-off-by: Bean Huo 
> ---
>  drivers/mmc/host/cavium.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
> index 95a41983c6c0..8fb7cbcf62ad 100644
> --- a/drivers/mmc/host/cavium.c
> +++ b/drivers/mmc/host/cavium.c
> @@ -654,8 +654,7 @@ static void cvm_mmc_dma_request(struct mmc_host *mmc,
> struct mmc_data *data;
> u64 emm_dma, addr;
>
> -   if (!mrq->data || !mrq->data->sg || !mrq->data->sg_len ||
> -   !mrq->stop || mrq->stop->opcode != MMC_STOP_TRANSMISSION) {
> +   if (!mrq->data || !mrq->data->sg || !mrq->data->sg_len) {
> dev_err(>card->dev, "Error: %s no data\n", __func__);
> goto error;
> }
> --
> 2.25.1
>


Re: [PATCH v1 1/2] Revert "PM: runtime: Update device status before letting suppliers suspend"

2021-03-19 Thread Ulf Hansson
On Thu, 18 Mar 2021 at 19:15, Rafael J. Wysocki  wrote:
>
> From: "Rafael J. Wysocki" 
>
> Revert commit 44cc89f76464 ("PM: runtime: Update device status
> before letting suppliers suspend") that introduced a race condition
> into __rpm_callback() which allowed a concurrent rpm_resume() to
> run and resume the device prematurely after its status had been
> changed to RPM_SUSPENDED by __rpm_callback().

Huh, the code path is not entirely easy to follow. :-)

Did you find this by code inspection or did you get an error report?

>
> Fixes: 44cc89f76464 ("PM: runtime: Update device status before letting 
> suppliers suspend")
> Link: 
> https://lore.kernel.org/linux-pm/24dfb6fc-5d54-6ee2-9195-26428b7ec...@intel.com/
> Reported by: Adrian Hunter 
> Cc: 4.10+  # 4.10+
> Signed-off-by: Rafael J. Wysocki 

Reviewed-by: Ulf Hansson 

Kind regards
Uffe


> ---
>  drivers/base/power/runtime.c | 62 +++-
>  1 file changed, 25 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
> index 18b82427d0cb..a46a7e30881b 100644
> --- a/drivers/base/power/runtime.c
> +++ b/drivers/base/power/runtime.c
> @@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct device *dev)
>  static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
> __releases(>power.lock) __acquires(>power.lock)
>  {
> -   bool use_links = dev->power.links_count > 0;
> -   bool get = false;
> int retval, idx;
> -   bool put;
> +   bool use_links = dev->power.links_count > 0;
>
> if (dev->power.irq_safe) {
> spin_unlock(>power.lock);
> -   } else if (!use_links) {
> -   spin_unlock_irq(>power.lock);
> } else {
> -   get = dev->power.runtime_status == RPM_RESUMING;
> -
> spin_unlock_irq(>power.lock);
>
> -   /* Resume suppliers if necessary. */
> -   if (get) {
> +   /*
> +* Resume suppliers if necessary.
> +*
> +* The device's runtime PM status cannot change until this
> +* routine returns, so it is safe to read the status outside 
> of
> +* the lock.
> +*/
> +   if (use_links && dev->power.runtime_status == RPM_RESUMING) {
> idx = device_links_read_lock();
>
> retval = rpm_get_suppliers(dev);
> @@ -355,36 +355,24 @@ static int __rpm_callback(int (*cb)(struct device *), 
> struct device *dev)
>
> if (dev->power.irq_safe) {
> spin_lock(>power.lock);
> -   return retval;
> -   }
> -
> -   spin_lock_irq(>power.lock);
> -
> -   if (!use_links)
> -   return retval;
> -
> -   /*
> -* If the device is suspending and the callback has returned success,
> -* drop the usage counters of the suppliers that have been reference
> -* counted on its resume.
> -*
> -* Do that if the resume fails too.
> -*/
> -   put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
> -   if (put)
> -   __update_runtime_status(dev, RPM_SUSPENDED);
> -   else
> -   put = get && retval;
> -
> -   if (put) {
> -   spin_unlock_irq(>power.lock);
> -
> -   idx = device_links_read_lock();
> +   } else {
> +   /*
> +* If the device is suspending and the callback has returned
> +* success, drop the usage counters of the suppliers that have
> +* been reference counted on its resume.
> +*
> +* Do that if resume fails too.
> +*/
> +   if (use_links
> +   && ((dev->power.runtime_status == RPM_SUSPENDING && 
> !retval)
> +   || (dev->power.runtime_status == RPM_RESUMING && 
> retval))) {
> +   idx = device_links_read_lock();
>
> -fail:
> -   rpm_put_suppliers(dev);
> + fail:
> +   rpm_put_suppliers(dev);
>
> -   device_links_read_unlock(idx);
> +   device_links_read_unlock(idx);
> +   }
>
> spin_lock_irq(>power.lock);
> }
> --
> 2.26.2
>
>
>
>


Re: [PATCH v1 2/2] PM: runtime: Defer suspending suppliers

2021-03-19 Thread Ulf Hansson
On Thu, 18 Mar 2021 at 19:15, Rafael J. Wysocki  wrote:
>
> From: Rafael J. Wysocki 
>
> Because the PM-runtime status of the device is not updated in
> __rpm_callback(), attempts to suspend the suppliers of the given
> device triggered by the rpm_put_suppliers() call in there may fail.
>
> To fix this (1) modify __rpm_callback() to avoid attempting to
> actually suspend the suppliers, but only decrease their PM-runtime
> usage counters and (2) make rpm_suspend() try to suspend the suppliers
> after changing the device's PM-runtime status, in analogy with the
> handling of the device's parent.
>
> Link: 
> https://lore.kernel.org/linux-pm/capdykfqm06kdw_p8wxsm4dijdbho4bb6t4k50uqqvr1_cos...@mail.gmail.com/
> Fixes: 21d5c57b3726 ("PM / runtime: Use device links")
> Reported-by: elaine.zhang 
> Diagnosed-by: Ulf Hansson 
> Signed-off-by: Rafael J. Wysocki 

Just a minor nitpick, see below. In any case:

Reviewed-by: Ulf Hansson 

> ---
>  drivers/base/power/runtime.c |   45 
> +--
>  1 file changed, 39 insertions(+), 6 deletions(-)
>
> Index: linux-pm/drivers/base/power/runtime.c
> ===
> --- linux-pm.orig/drivers/base/power/runtime.c
> +++ linux-pm/drivers/base/power/runtime.c
> @@ -305,7 +305,7 @@ static int rpm_get_suppliers(struct devi
> return 0;
>  }
>
> -static void rpm_put_suppliers(struct device *dev)
> +static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
>  {
> struct device_link *link;
>
> @@ -313,10 +313,30 @@ static void rpm_put_suppliers(struct dev
> device_links_read_lock_held()) {
>
> while (refcount_dec_not_one(>rpm_active))
> -   pm_runtime_put(link->supplier);
> +   pm_runtime_put_noidle(link->supplier);
> +
> +   if (try_to_suspend)
> +   pm_request_idle(link->supplier);
> }
>  }
>
> +static void rpm_put_suppliers(struct device *dev)
> +{
> +   __rpm_put_suppliers(dev, true);
> +}
> +
> +static void rpm_try_to_suspend_suppliers(struct device *dev)

Maybe "rpm_suspend_suppliers" is sufficient for the name of the
function, but I have no strong opinion.

> +{
> +   struct device_link *link;
> +   int idx = device_links_read_lock();
> +
> +   list_for_each_entry_rcu(link, >links.suppliers, c_node,
> +   device_links_read_lock_held())
> +   pm_request_idle(link->supplier);
> +
> +   device_links_read_unlock(idx);
> +}
> +

[...]

Kind regards
Uffe


Re: [PATCH] firmware: imx: scu-pd: Update comments for single global power domain

2021-03-19 Thread Ulf Hansson
On Fri, 19 Mar 2021 at 04:31, Aisheng Dong  wrote:
>
> Hi Ulf,
>
> > From: Ulf Hansson 
> > Sent: Wednesday, March 17, 2021 5:31 PM
> >
> > Since the introduction of the PM domain support for the scu-pd, the genpd
> > framework has been continuously improved. More preciously, using a single
> > global power domain can quite easily be deployed for imx platforms.
> >
> > To avoid confusions, let's therefore make an update to the comments about
> > the missing pieces.
> >
> > Signed-off-by: Ulf Hansson 
>
> Thanks for the update.
> Reviewed-by: Dong Aisheng 
>
> BTW, I'm still uncertain if the new approach can finally work well for i.MX 
> as SCU PD
> also supports multiple low power state.
> I could investigate it more when I adding multi low power states support.

The multiple low power states are currently only supported per genpd
and not per device. So, yes, in principle you could have one genpd per
device as you currently model it, to support this.

Although, thinking long term wise, we probably want something else
that doesn't rely on the device to be attached to a genpd to support
this use case.

In the past, I have been talking to different people from various SoC
vendors and it looks like the use case is there, but it's kind of
messy to support it. I would certainly be very interested to hear
about your use case, would you mind sharing some more about this?

Moreover, note that, there is a limitation in the genpd infrastructure
when you build a hierarchy with parent/childs genpds, when each genpd
has multiple idle states. That is, a parent-genpd may be allowed to
enter any of its idle states, no matter what idle state that has been
selected for the child-genpd. As a matter of fact, I am about to fix
this problem quite soon. Is perhaps this something that could be
valuable for your platforms too?

[...]

Kind regards
Uffe


[PATCH] firmware: imx: scu-pd: Update comments for single global power domain

2021-03-17 Thread Ulf Hansson
Since the introduction of the PM domain support for the scu-pd, the genpd
framework has been continuously improved. More preciously, using a single
global power domain can quite easily be deployed for imx platforms.

To avoid confusions, let's therefore make an update to the comments about
the missing pieces.

Signed-off-by: Ulf Hansson 
---
 drivers/firmware/imx/scu-pd.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 08533ee67626..6e178a63442d 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -29,6 +29,10 @@
  *The framework needs some proper extension to support multi power
  *domain cases.
  *
+ *Update: Genpd assigns the ->of_node for the virtual device before it
+ *invokes ->attach_dev() callback, hence parsing for device resources via
+ *DT should work fine.
+ *
  * 2. It also breaks most of current drivers as the driver probe sequence
  *behavior changed if removing ->power_on|off() callback and use
  *->start() and ->stop() instead. genpd_dev_pm_attach will only power
@@ -39,8 +43,11 @@
  *domain enabled will trigger a HW access error. That means we need fix
  *most drivers probe sequence with proper runtime pm.
  *
- * In summary, we need fix above two issue before being able to switch to
- * the "single global power domain" way.
+ *Update: Runtime PM support isn't necessary. Instead, this can easily be
+ *fixed in drivers by adding a call to dev_pm_domain_start() during probe.
+ *
+ * In summary, the second part needs to be addressed via minor updates to the
+ * relevant drivers, before the "single global power domain" model can be used.
  *
  */
 
-- 
2.25.1



[GIT PULL] MMC fixes for v5.12-rc3

2021-03-12 Thread Ulf Hansson
Hi Linus,

Here's a PR with a couple of MMC fixes intended for v5.12-rc3. Details about the
highlights are as usual found in the signed tag.

Please pull this in!

Kind regards
Ulf Hansson


The following changes since commit a38fd8748464831584a19438cbb3082b5a2dab15:

  Linux 5.12-rc2 (2021-03-05 17:33:41 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git tags/mmc-v5.12-rc2

for you to fetch changes up to f06391c45e83f9a731045deb23df7cc3814fd795:

  mmc: cqhci: Fix random crash when remove mmc module/card (2021-03-09 10:00:52 
+0100)


MMC core:
 - Fix partition switch time for eMMC

MMC host:
 - mmci: Enforce R1B response to fix busy detection for the stm32 variants
 - cqhci: Fix crash when removing mmc module/card


Adrian Hunter (1):
  mmc: core: Fix partition switch time for eMMC

Frank Li (1):
  mmc: cqhci: Fix random crash when remove mmc module/card

Yann Gautier (1):
  mmc: mmci: Add MMC_CAP_NEED_RSP_BUSY for the stm32 variants

 drivers/mmc/core/bus.c  | 11 +--
 drivers/mmc/core/mmc.c  | 15 +++
 drivers/mmc/host/mmci.c | 10 +-
 3 files changed, 25 insertions(+), 11 deletions(-)


Re: [PATCH v2 01/14] opp: Add devres wrapper for dev_pm_opp_set_clkname

2021-03-12 Thread Ulf Hansson
On Fri, 12 Mar 2021 at 06:33, Viresh Kumar  wrote:
>
> On 11-03-21, 22:20, Dmitry Osipenko wrote:
> > +struct opp_table *devm_pm_opp_set_clkname(struct device *dev, const char 
> > *name)
> > +{
> > + struct opp_table *opp_table;
> > + int err;
> > +
> > + opp_table = dev_pm_opp_set_clkname(dev, name);
> > + if (IS_ERR(opp_table))
> > + return opp_table;
> > +
> > + err = devm_add_action_or_reset(dev, devm_pm_opp_clkname_release, 
> > opp_table);
> > + if (err)
> > + opp_table = ERR_PTR(err);
> > +
> > + return opp_table;
> > +}
>
> I wonder if we still need to return opp_table from here, or a simple
> integer is fine.. The callers shouldn't be required to use the OPP
> table directly anymore I believe and so better simplify the return
> part of this and all other routines you are adding here..

Yes, please. I was thinking along the same lines, when I reviewed the
mmc patch (patch9).

>
> If there is a user which needs the opp_table, let it use the regular
> non-devm variant.

Kind regards
Uffe


Re: linux-next: Signed-off-by missing for commit in the mmc tree

2021-03-11 Thread Ulf Hansson
On Tue, 9 Mar 2021 at 22:15, Stephen Rothwell  wrote:
>
> Hi all,
>
> Commit
>
>   a7856f326331 ("mmc: dw_mmc: simplify optional reset handling")
>
> is missing a Signed-off-by from its committer.

Taken care of, thanks for reporting!

>
> --
> Cheers,
> Stephen Rothwell

Kind regards
Uffe


Re: [PATCH] mmc: sdhci-pci: Avoid comma separated statements

2021-03-11 Thread Ulf Hansson
On Thu, 11 Mar 2021 at 11:14, Jisheng Zhang  wrote:
>
> Use semicolons.
>
> Signed-off-by: Jisheng Zhang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-pci-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-pci-core.c 
> b/drivers/mmc/host/sdhci-pci-core.c
> index 9552708846ca..62799c1d9c0c 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -958,7 +958,7 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot 
> *slot)
> slot->host->mmc->caps2 |= MMC_CAP2_CQE;
>
> if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
> -   slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
> +   slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
> slot->host->mmc_host_ops.hs400_enhanced_strobe =
> intel_hs400_enhanced_strobe;
> slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
> --
> 2.30.2
>


Re: [PATCH] mmc: sdhci: Use "mmc" directly rather than "host->mmc"

2021-03-11 Thread Ulf Hansson
On Thu, 11 Mar 2021 at 10:40, Jisheng Zhang  wrote:
>
> Clean up the code to use the "mmc" directly instead of "host->mmc".
> If the code sits in hot code path, this clean up also brings trvial
> performance improvement. Take the sdhci_post_req() for example:
>
> before the patch:
>  ...
>  8d0:   a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4:   910003fdmov x29, sp
>  8d8:   f9000bf3str x19, [sp, #16]
>  8dc:   f9400833ldr x19, [x1, #16]
>  8e0:   b9404261ldr w1, [x19, #64]
>  8e4:   34000161cbz w1, 910 
>  8e8:   f9424400ldr x0, [x0, #1160]
>  8ec:   d284mov x4, #0x0// #0
>  8f0:   b9401a61ldr w1, [x19, #24]
>  8f4:   b9403262ldr w2, [x19, #48]
>  8f8:   f940ldr x0, [x0]
>  8fc:   f278003ftst x1, #0x100
>  900:   f9401e61ldr x1, [x19, #56]
>  904:   1a9f17e3csetw3, eq  // eq = none
>  908:   11000463add w3, w3, #0x1
>  90c:   9400bl  0 
>  ...
>
> After the patch:
>  ...
>  8d0:   a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4:   910003fdmov x29, sp
>  8d8:   f9000bf3str x19, [sp, #16]
>  8dc:   f9400833ldr x19, [x1, #16]
>  8e0:   b9404261ldr w1, [x19, #64]
>  8e4:   34000141cbz w1, 90c 
>  8e8:   b9401a61ldr w1, [x19, #24]
>  8ec:   d284mov x4, #0x0// #0
>  8f0:   b9403262ldr w2, [x19, #48]
>  8f4:   f940ldr x0, [x0]
>  8f8:   f278003ftst x1, #0x100
>  8fc:   f9401e61ldr x1, [x19, #56]
>  900:   1a9f17e3csetw3, eq  // eq = none
>  904:   11000463add w3, w3, #0x1
>  908:   9400bl  0 
>  ...
>
> We saved one ldr instruction: "ldr x0, [x0, #1160]"
>
> Signed-off-by: Jisheng Zhang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci.c | 33 -
>  1 file changed, 16 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2d73407ee52e..b1afabab9cae 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -907,7 +907,7 @@ static void sdhci_calc_sw_timeout(struct sdhci_host *host,
>
> if (data) {
> blksz = data->blksz;
> -   freq = host->mmc->actual_clock ? : host->clock;
> +   freq = mmc->actual_clock ? : host->clock;
> transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width);
> do_div(transfer_time, freq);
> /* multiply by '2' to account for any unknowns */
> @@ -2269,14 +2269,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct 
> mmc_ios *ios)
>
> if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
> host->clock) {
> -   host->timeout_clk = host->mmc->actual_clock ?
> -   host->mmc->actual_clock / 
> 1000 :
> +   host->timeout_clk = mmc->actual_clock ?
> +   mmc->actual_clock / 1000 :
> host->clock / 1000;
> -   host->mmc->max_busy_timeout =
> +   mmc->max_busy_timeout =
> host->ops->get_max_timeout_count ?
> host->ops->get_max_timeout_count(host) :
> 1 << 27;
> -   host->mmc->max_busy_timeout /= host->timeout_clk;
> +   mmc->max_busy_timeout /= host->timeout_clk;
> }
> }
>
> @@ -2399,7 +2399,7 @@ static int sdhci_get_cd(struct mmc_host *mmc)
> return 0;
>
> /* If nonremovable, assume that the card is always present. */
> -   if (!mmc_card_is_removable(host->mmc))
> +   if (!mmc_card_is_removable(mmc))
> return 1;
>
> /*
> @@ -2489,14 +2489,14 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int 
> enable)
> unsigned long flags;
>
> if (enable)
> -   pm_runtime_get_noresume(host->mmc->parent);
> +   pm_runtime_get_noresume(mmc->parent);
>
> spin_lock_irqsave(>lock, flags);
> sdhci_enable_sdio_irq_nolock(host, enable);
> spin_unlock_irqrestore(>lock, flags);
>
> if (!enable)
> -   pm_runtime_put_noidle(host->mmc->parent);
> +   pm_runtime_put_noidle(mmc->parent);
>  }
>  EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq);
>
> @@ -2837,7 

Re: [PATCH] mmc: sdio: fix a typo in the comment of SDIO_SD_REV_3_00

2021-03-11 Thread Ulf Hansson
On Thu, 11 Mar 2021 at 10:42, Jisheng Zhang  wrote:
>
> I believe "Spev" is typo, should be "Spec".
>
> Signed-off-by: Jisheng Zhang 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  include/linux/mmc/sdio.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
> index e28769991e82..2a05d1ac4f0e 100644
> --- a/include/linux/mmc/sdio.h
> +++ b/include/linux/mmc/sdio.h
> @@ -82,7 +82,7 @@
>  #define  SDIO_SD_REV_1_01  0   /* SD Physical Spec Version 1.01 */
>  #define  SDIO_SD_REV_1_10  1   /* SD Physical Spec Version 1.10 */
>  #define  SDIO_SD_REV_2_00  2   /* SD Physical Spec Version 2.00 */
> -#define  SDIO_SD_REV_3_00  3   /* SD Physical Spev Version 3.00 */
> +#define  SDIO_SD_REV_3_00  3   /* SD Physical Spec Version 3.00 */
>
>  #define SDIO_CCCR_IOEx 0x02
>  #define SDIO_CCCR_IORx 0x03
> --
> 2.30.2
>


Re: [PATCH] mmc: sdhci: Use "mmc" directly rather than "host->mmc"

2021-03-11 Thread Ulf Hansson
On Thu, 11 Mar 2021 at 10:40, Jisheng Zhang  wrote:
>
> Clean up the code to use the "mmc" directly instead of "host->mmc".
> If the code sits in hot code path, this clean up also brings trvial
> performance improvement. Take the sdhci_post_req() for example:
>
> before the patch:
>  ...
>  8d0:   a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4:   910003fdmov x29, sp
>  8d8:   f9000bf3str x19, [sp, #16]
>  8dc:   f9400833ldr x19, [x1, #16]
>  8e0:   b9404261ldr w1, [x19, #64]
>  8e4:   34000161cbz w1, 910 
>  8e8:   f9424400ldr x0, [x0, #1160]
>  8ec:   d284mov x4, #0x0// #0
>  8f0:   b9401a61ldr w1, [x19, #24]
>  8f4:   b9403262ldr w2, [x19, #48]
>  8f8:   f940ldr x0, [x0]
>  8fc:   f278003ftst x1, #0x100
>  900:   f9401e61ldr x1, [x19, #56]
>  904:   1a9f17e3csetw3, eq  // eq = none
>  908:   11000463add w3, w3, #0x1
>  90c:   9400bl  0 
>  ...
>
> After the patch:
>  ...
>  8d0:   a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4:   910003fdmov x29, sp
>  8d8:   f9000bf3str x19, [sp, #16]
>  8dc:   f9400833ldr x19, [x1, #16]
>  8e0:   b9404261ldr w1, [x19, #64]
>  8e4:   34000141cbz w1, 90c 
>  8e8:   b9401a61ldr w1, [x19, #24]
>  8ec:   d284mov x4, #0x0// #0
>  8f0:   b9403262ldr w2, [x19, #48]
>  8f4:   f940ldr x0, [x0]
>  8f8:   f278003ftst x1, #0x100
>  8fc:   f9401e61ldr x1, [x19, #56]
>  900:   1a9f17e3csetw3, eq  // eq = none
>  904:   11000463add w3, w3, #0x1
>  908:   9400bl  0 
>  ...
>
> We saved one ldr instruction: "ldr x0, [x0, #1160]"

Nice!

Even if I think the cleanup of code makes sense alone.

>
> Signed-off-by: Jisheng Zhang 
> ---
>  drivers/mmc/host/sdhci.c | 33 -
>  1 file changed, 16 insertions(+), 17 deletions(-)
>

[...]

> @@ -2489,14 +2489,14 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int 
> enable)
> unsigned long flags;
>
> if (enable)
> -   pm_runtime_get_noresume(host->mmc->parent);
> +   pm_runtime_get_noresume(mmc->parent);

Maybe use mmc_dev(mmc) instead? At least I think I would appreciate
consistency in the entire c-file, today it seems like both
"mmc->parent" and mmc_dev(mmc) are being used.

[...]

Kind regards
Uffe


[PATCH] mmc: core: Fix hanging on I/O during system suspend for removable cards

2021-03-10 Thread Ulf Hansson
The mmc core uses a PM notifier to temporarily during system suspend, turn
off the card detection mechanism for removal/insertion of (e)MMC/SD/SDIO
cards. Additionally, the notifier may be used to remove an SDIO card
entirely, if a corresponding SDIO functional driver don't have the system
suspend/resume callbacks assigned. This behaviour has been around for a
very long time.

However, a recent bug report tells us there are problems with this
approach. More precisely, when receiving the PM_SUSPEND_PREPARE
notification, we may end up hanging on I/O to be completed, thus also
preventing the system from getting suspended.

In the end what happens, is that the cancel_delayed_work_sync() in
mmc_pm_notify() ends up waiting for mmc_rescan() to complete - and since
mmc_rescan() wants to claim the host, it needs to wait for the I/O to be
completed first.

Typically, this problem is triggered in Android, if there is ongoing I/O
while the user decides to suspend, resume and then suspend the system
again. This due to that after the resume, an mmc_rescan() work gets punted
to the workqueue, which job is to verify that the card remains inserted
after the system has resumed.

To fix this problem, userspace needs to become frozen to suspend the I/O,
prior to turning off the card detection mechanism. Therefore, let's drop
the PM notifiers for mmc subsystem altogether and rely on the card
detection to be turned off/on as a part of the system_freezable_wq, that we
are already using.

Moreover, to allow and SDIO card to be removed during system suspend, let's
manage this from a ->prepare() callback, assigned at the mmc_host_class
level. In this way, we can use the parent device (the mmc_host_class
device), to remove the card device that is the child, in the
device_prepare() phase.

Reported-by: Kiwoong Kim 
Cc: sta...@vger.kernel.org
Signed-off-by: Ulf Hansson 
---
 drivers/mmc/core/core.c  | 74 
 drivers/mmc/core/core.h  |  8 -
 drivers/mmc/core/host.c  | 40 --
 drivers/mmc/core/sdio.c  | 28 +++
 include/linux/mmc/host.h |  3 --
 5 files changed, 59 insertions(+), 94 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9c13f7a52699..f194940c5974 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2269,80 +2269,6 @@ void mmc_stop_host(struct mmc_host *host)
mmc_release_host(host);
 }
 
-#ifdef CONFIG_PM_SLEEP
-/* Do the card removal on suspend if card is assumed removeable
- * Do that in pm notifier while userspace isn't yet frozen, so we will be able
-   to sync the card.
-*/
-static int mmc_pm_notify(struct notifier_block *notify_block,
-   unsigned long mode, void *unused)
-{
-   struct mmc_host *host = container_of(
-   notify_block, struct mmc_host, pm_notify);
-   unsigned long flags;
-   int err = 0;
-
-   switch (mode) {
-   case PM_HIBERNATION_PREPARE:
-   case PM_SUSPEND_PREPARE:
-   case PM_RESTORE_PREPARE:
-   spin_lock_irqsave(>lock, flags);
-   host->rescan_disable = 1;
-   spin_unlock_irqrestore(>lock, flags);
-   cancel_delayed_work_sync(>detect);
-
-   if (!host->bus_ops)
-   break;
-
-   /* Validate prerequisites for suspend */
-   if (host->bus_ops->pre_suspend)
-   err = host->bus_ops->pre_suspend(host);
-   if (!err)
-   break;
-
-   if (!mmc_card_is_removable(host)) {
-   dev_warn(mmc_dev(host),
-"pre_suspend failed for non-removable host: "
-"%d\n", err);
-   /* Avoid removing non-removable hosts */
-   break;
-   }
-
-   /* Calling bus_ops->remove() with a claimed host can deadlock */
-   host->bus_ops->remove(host);
-   mmc_claim_host(host);
-   mmc_detach_bus(host);
-   mmc_power_off(host);
-   mmc_release_host(host);
-   host->pm_flags = 0;
-   break;
-
-   case PM_POST_SUSPEND:
-   case PM_POST_HIBERNATION:
-   case PM_POST_RESTORE:
-
-   spin_lock_irqsave(>lock, flags);
-   host->rescan_disable = 0;
-   spin_unlock_irqrestore(>lock, flags);
-   _mmc_detect_change(host, 0, false);
-
-   }
-
-   return 0;
-}
-
-void mmc_register_pm_notifier(struct mmc_host *host)
-{
-   host->pm_notify.notifier_call = mmc_pm_notify;
-   register_pm_notifier(>pm_notify);
-}
-
-void mmc_unregister_pm_notifier(struct mmc_host *host)
-{
-   unregister_pm_notifier(>pm_notify);
-}
-#endif
-
 static int __init mmc_init(void)
 {
int ret;
diff --git a/drivers/mmc/core/core.h

Re: [PATCH] mmc: via-sdmmc: remove unneeded variable 'ret'

2021-03-09 Thread Ulf Hansson
On Tue, 9 Mar 2021 at 07:48, Yang Li  wrote:
>
> Fix the following coccicheck warning:
> ./drivers/mmc/host/via-sdmmc.c:1274:5-8: Unneeded variable: "ret".
> Return "0" on line 1295
>
> Reported-by: Abaci Robot 
> Signed-off-by: Yang Li 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/via-sdmmc.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
> index 4f4c081..a1d0985 100644
> --- a/drivers/mmc/host/via-sdmmc.c
> +++ b/drivers/mmc/host/via-sdmmc.c
> @@ -1271,7 +1271,6 @@ static int __maybe_unused via_sd_suspend(struct device 
> *dev)
>  static int __maybe_unused via_sd_resume(struct device *dev)
>  {
> struct via_crdr_mmc_host *sdhost;
> -   int ret = 0;
> u8 gatt;
>
> sdhost = dev_get_drvdata(dev);
> @@ -1292,7 +1291,7 @@ static int __maybe_unused via_sd_resume(struct device 
> *dev)
> via_restore_pcictrlreg(sdhost);
> via_init_sdc_pm(sdhost);
>
> -   return ret;
> +   return 0;
>  }
>
>  static SIMPLE_DEV_PM_OPS(via_sd_pm_ops, via_sd_suspend, via_sd_resume);
> --
> 1.8.3.1
>


Re: [PATCH] memstick: core: fix error return code of mspro_block_resume()

2021-03-09 Thread Ulf Hansson
On Fri, 5 Mar 2021 at 03:14, Jia-Ju Bai  wrote:
>
> When mspro_block_init_card() fails, no error return code of
> mspro_block_resume() is assigned.
> To fix this bug, rc is assigned with the return value of
> mspro_block_init_card(), and then rc is checked.
>
> Reported-by: TOTE Robot 
> Signed-off-by: Jia-Ju Bai 

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/memstick/core/mspro_block.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/memstick/core/mspro_block.c 
> b/drivers/memstick/core/mspro_block.c
> index afb892e7ffc6..cf7fe0d58ee7 100644
> --- a/drivers/memstick/core/mspro_block.c
> +++ b/drivers/memstick/core/mspro_block.c
> @@ -1382,7 +1382,8 @@ static int mspro_block_resume(struct memstick_dev *card)
>
> new_msb->card = card;
> memstick_set_drvdata(card, new_msb);
> -   if (mspro_block_init_card(card))
> +   rc = mspro_block_init_card(card);
> +   if (rc)
> goto out_free;
>
> for (cnt = 0; new_msb->attr_group.attrs[cnt]
> --
> 2.17.1
>


Re: [BUG] memstick: core: missing error return code in msb_resume()

2021-03-09 Thread Ulf Hansson
On Fri, 5 Mar 2021 at 03:45, Jia-Ju Bai  wrote:
>
> My static analysis tool reports that no error return code is assigned in
> error handling code of msb_resume().
> However, many other drivers assign error return code in xxx_resume(),
> such as sky2_resume() and e1000_resume().
> I wonder whether this is intentional?

It's for sure intentional, but it really doesn't matter that much as
we are probably in rather dodgy state anyways.

Of course, propagating error codes upwards in the stack is always good
practise, so feel free to add it.

Kind regards
Uffe


Re: [RFC 0/2] sdhci-iproc CMD timeouts

2021-03-09 Thread Ulf Hansson
On Thu, 25 Feb 2021 at 10:53, Nicolas Saenz Julienne
 wrote:
>
> I'm seeing a rather odd behavior from sdhci-iproc's integration in BCM2711
> (Raspberry Pi 4's SoC), and would appreciate some opinions.
>
> The controller will timeout on SDHCI CMDs under the following conditions:
>
>  - No SD card plugged in (the card polling thread is running, CD irq 
> disabled).
>  - BCM2711's VPU clock[1] configured at 500MHz or more, lower clocks are OK.
>
> There is no specific command that will time out, it seems random.
>
> Here's what I found out. The SDHCI controller runs at 100MHz, by bumping the
> frequency to 150MHz the issue disapears. Might be pure luck, or maybe I hit 
> the
> nail and it's proper interference. Can't say.

As you probably know, I don't have the in-depth knowledge about this
HW. Although, let me provide a very vague guess. Could be that the
controller needs a higher clock rate to stay within some spec, for an
OPP/voltage domain for example?

In any case, assuming you get some confirmation from the Broadcom
folkz that this makes sense, you  need to update the DT doc bindings
to add the clock-frequency property. In regards to this, please take
the opportunity to convert from legacy DT doc format
(brcm,sdhci-iproc.txt) into the new yaml format.

Kind regards
Uffe

>
> Regards,
> Nicolas
>
> ---
>
> [1] For those who are not aware, here's the relationship between VPU's clock
> and emmc2's:
>
>  osc5400
> plld  300091
>plld_per75023
>   emmc2149882908
> pllc  299988
>pllc_core0  6
>   vpu  49998
>
> Nicolas Saenz Julienne (2):
>   ARM: dts: Fix-up EMMC2 controller's frequency
>   mmc: sdhci-iproc: Set clock frequency as per DT
>
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  6 ++
>  drivers/mmc/host/sdhci-iproc.c| 10 ++
>  2 files changed, 16 insertions(+)
>
> --
> 2.30.1
>


[PATCH] PM: domains: Don't runtime resume devices at genpd_prepare()

2021-03-04 Thread Ulf Hansson
Runtime resuming a device upfront in the genpd_prepare() callback, to check
if there is a wakeup pending for it, seems like an unnecessary thing to do.
The PM core already manages these kind of things in a common way in
__device_suspend(), via calling pm_runtime_barrier() and
pm_wakeup_pending().

Therefore, let's simply drop this behaviour from genpd_prepare().

Note that, this change is applicable only for devices that are attached to
a genpd that has the GENPD_FLAG_ACTIVE_WAKEUP set (Renesas, Mediatek, and
Rockchip platforms). Moreover, a driver that needs to restore power for its
device to re-configure it for a system wakeup, may still call
pm_runtime_get_sync(), for example, to do this.

Signed-off-by: Ulf Hansson 
---
 drivers/base/power/domain.c | 36 
 1 file changed, 36 deletions(-)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 78c310d3179d..b6a782c31613 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1087,34 +1087,6 @@ static void genpd_sync_power_on(struct generic_pm_domain 
*genpd, bool use_lock,
genpd->status = GENPD_STATE_ON;
 }
 
-/**
- * resume_needed - Check whether to resume a device before system suspend.
- * @dev: Device to check.
- * @genpd: PM domain the device belongs to.
- *
- * There are two cases in which a device that can wake up the system from sleep
- * states should be resumed by genpd_prepare(): (1) if the device is enabled
- * to wake up the system and it has to remain active for this purpose while the
- * system is in the sleep state and (2) if the device is not enabled to wake up
- * the system from sleep states and it generally doesn't generate wakeup 
signals
- * by itself (those signals are generated on its behalf by other parts of the
- * system).  In the latter case it may be necessary to reconfigure the device's
- * wakeup settings during system suspend, because it may have been set up to
- * signal remote wakeup from the system's working state as needed by runtime 
PM.
- * Return 'true' in either of the above cases.
- */
-static bool resume_needed(struct device *dev,
- const struct generic_pm_domain *genpd)
-{
-   bool active_wakeup;
-
-   if (!device_can_wakeup(dev))
-   return false;
-
-   active_wakeup = genpd_is_active_wakeup(genpd);
-   return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
-}
-
 /**
  * genpd_prepare - Start power transition of a device in a PM domain.
  * @dev: Device to start the transition of.
@@ -1135,14 +1107,6 @@ static int genpd_prepare(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;
 
-   /*
-* If a wakeup request is pending for the device, it should be woken up
-* at this point and a system wakeup event should be reported if it's
-* set up to wake up the system from sleep states.
-*/
-   if (resume_needed(dev, genpd))
-   pm_runtime_resume(dev);
-
genpd_lock(genpd);
 
if (genpd->prepared_count++ == 0)
-- 
2.25.1



Re: [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap

2021-03-04 Thread Ulf Hansson
On Thu, 4 Mar 2021 at 16:16,  wrote:
>
> On 2021-03-04 19:19, Ulf Hansson wrote:
> > On Wed, 3 Mar 2021 at 09:32, Pradeep P V K 
> > wrote:
> >>
> >> From: Pradeep P V K 
> >>
> >> For data read commands, SDHC may initiate data transfers even before
> >> it
> >> completely process the command response. In case command itself fails,
> >> driver un-maps the memory associated with data transfer but this
> >> memory
> >> can still be accessed by SDHC for the already initiated data transfer.
> >> This scenario can lead to un-mapped memory access error.
> >>
> >> To avoid this scenario, reset SDHC (when command fails) prior to
> >> un-mapping memory. Resetting SDHC ensures that all in-flight data
> >> transfers are either aborted or completed. So we don't run into this
> >> scenario.
> >>
> >> Swap the reset, un-map steps sequence in sdhci_request_done().
> >>
> >> Changes since V1:
> >> - Added an empty line and fixed the comment style.
> >> - Retained the Acked-by signoff.
> >>
> >> Suggested-by: Veerabhadrarao Badiganti 
> >> Signed-off-by: Pradeep P V K 
> >> Acked-by: Adrian Hunter 
>
> Hi Uffe,
> >
> > Seems like it might be a good idea to tag this for stable? I did that,
> > but awaiting for your confirmation.
> >
> Yes, this fix is applicable for all stable starting from 4.9 (n/a for
> 4.4).
> Kindly go ahead.
>
> > So, applied for next, thanks!
> >
> > Kind regards
> > Uffe
> >
> Thanks and Regards,
> Pradeep

Thanks for confirming, I have updated the stable tag.

Kind regards
Uffe

>
> >
> >> ---
> >>  drivers/mmc/host/sdhci.c | 60
> >> +---
> >>  1 file changed, 31 insertions(+), 29 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >> index 646823d..130fd2d 100644
> >> --- a/drivers/mmc/host/sdhci.c
> >> +++ b/drivers/mmc/host/sdhci.c
> >> @@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct
> >> sdhci_host *host)
> >> }
> >>
> >> /*
> >> +* The controller needs a reset of internal state machines
> >> +* upon error conditions.
> >> +*/
> >> +   if (sdhci_needs_reset(host, mrq)) {
> >> +   /*
> >> +* Do not finish until command and data lines are
> >> available for
> >> +* reset. Note there can only be one other mrq, so it
> >> cannot
> >> +* also be in mrqs_done, otherwise host->cmd and
> >> host->data_cmd
> >> +* would both be null.
> >> +*/
> >> +   if (host->cmd || host->data_cmd) {
> >> +   spin_unlock_irqrestore(>lock, flags);
> >> +   return true;
> >> +   }
> >> +
> >> +   /* Some controllers need this kick or reset won't work
> >> here */
> >> +   if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
> >> +   /* This is to force an update */
> >> +   host->ops->set_clock(host, host->clock);
> >> +
> >> +   /*
> >> +* Spec says we should do both at the same time, but
> >> Ricoh
> >> +* controllers do not like that.
> >> +*/
> >> +   sdhci_do_reset(host, SDHCI_RESET_CMD);
> >> +   sdhci_do_reset(host, SDHCI_RESET_DATA);
> >> +
> >> +   host->pending_reset = false;
> >> +   }
> >> +
> >> +   /*
> >>  * Always unmap the data buffers if they were mapped by
> >>  * sdhci_prepare_data() whenever we finish with a request.
> >>  * This avoids leaking DMA mappings on error.
> >> @@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct
> >> sdhci_host *host)
> >> }
> >> }
> >>
> >> -   /*
> >> -* The controller needs a reset of internal state machines
> >> -* upon error conditions.
> >> -*/
> >> -   if (sdhci_needs_reset(host, mrq)) {
> >> -   /*
> >> -* Do not finish until command and data lines are
> >&

Re: [PATCH] mmc: Try power cycling card if command request times out

2021-03-04 Thread Ulf Hansson
On Thu, 4 Mar 2021 at 15:59, Marten Lindahl  wrote:
>
> On Thu, Mar 04, 2021 at 03:06:54PM +0100, Ulf Hansson wrote:
> > On Thu, 4 Mar 2021 at 14:48, Marten Lindahl  wrote:
> > >
> > > Hi Ulf! My apologies for the delay.
> > >
> > > On Tue, Mar 02, 2021 at 09:45:02AM +0100, Ulf Hansson wrote:
> > > > On Mon, 1 Mar 2021 at 22:59, Marten Lindahl  wrote:
> > > > >
> > > > > Hi Ulf!
> > > > >
> > > > > Thank you for your comments!
> > > > >
> > > > > On Mon, Mar 01, 2021 at 09:50:56AM +0100, Ulf Hansson wrote:
> > > > > > + Adrian
> > > > > >
> > > > > > On Tue, 16 Feb 2021 at 23:43, Mårten Lindahl 
> > > > > >  wrote:
> > > > > > >
> > > > > > > Sometimes SD cards that has been run for a long time enters a 
> > > > > > > state
> > > > > > > where it cannot by itself be recovered, but needs a power cycle 
> > > > > > > to be
> > > > > > > operational again. Card status analysis has indicated that the 
> > > > > > > card can
> > > > > > > end up in a state where all external commands are ignored by the 
> > > > > > > card
> > > > > > > since it is halted by data timeouts.
> > > > > > >
> > > > > > > If the card has been heavily used for a long time it can be 
> > > > > > > weared out,
> > > > > > > and should typically be replaced. But on some tests, it shows 
> > > > > > > that the
> > > > > > > card can still be functional after a power cycle, but as it 
> > > > > > > requires an
> > > > > > > operator to do it, the card can remain in a non-operational state 
> > > > > > > for a
> > > > > > > long time until the problem has been observed by the operator.
> > > > > > >
> > > > > > > This patch adds function to power cycle the card in case it does 
> > > > > > > not
> > > > > > > respond to a command, and then resend the command if the power 
> > > > > > > cycle
> > > > > > > was successful. This procedure will be tested 1 time before 
> > > > > > > giving up,
> > > > > > > and resuming host operation as normal.
> > > > > >
> > > > > > I assume the context above is all about the ioctl interface?
> > > > > >
> > > > >
> > > > > Yes, that's correct. The problem we have seen is triggered by ioctls.
> > > > >
> > > > > > So, when the card enters this non functional state, have you tried
> > > > > > just reading a block through the regular I/O interface. Does it
> > > > > > trigger a power cycle of the card - and then makes it functional
> > > > > > again?
> > > > > >
> > > > >
> > > > > Yes, we have tried that, and it does trigger a power cycle, making 
> > > > > the card
> > > > > operational again. But as it requires an operator to trigger it, I 
> > > > > thought
> > > > > it might be something that could be automated here. At least once.
> > > >
> > > > Not sure what you mean by operator here? In the end it's a userspace
> > > > program running and I assume it can deal with error paths. :-)
> > > >
> > > > In any case, I understand your point.
> > > >
> > >
> > > Yes, we have a userspace program. So if the userspace program will try to
> > > restore the card in a situation such as the one we are trying to solve
> > > here, how shall it perform it? Is it expected that a ioctl CMD0 request
> > > should be enough, or is there any other support for a userspace program to
> > > reset the card?
> >
> > Correct, there is no way for userspace to reset cards through an ioctl.
> >
> > >
> > > If it falls on a ioctl command to reset the card, how do we handle the 
> > > case
> > > where the ioctl times out anyway? Or is the only way for a userspace 
> > > program
> > > to restore the card, to make a block transfer that fails?
> >
> > Yes, that is what I was thinking. According to the use case you have
> > described, this should be possible for you to implement as a part of
> > your userspace program, no?
>
> Ok, I will discuss that with the people maintaining the userspace program :)
>
> But would it be of interest to review a patch introducing a more clean card
> reset request, without block transfers?

Well, if you can solve it with block transfers that's the preferred
option, in my opinion.

As I stated earlier, my main issue with the HW reset through the ioctl
interface, is that we don't know what combination of
request/command/response we should be doing a reset for.

Kind regards
Uffe


Re: [PATCH] mmc: Try power cycling card if command request times out

2021-03-04 Thread Ulf Hansson
On Thu, 4 Mar 2021 at 14:48, Marten Lindahl  wrote:
>
> Hi Ulf! My apologies for the delay.
>
> On Tue, Mar 02, 2021 at 09:45:02AM +0100, Ulf Hansson wrote:
> > On Mon, 1 Mar 2021 at 22:59, Marten Lindahl  wrote:
> > >
> > > Hi Ulf!
> > >
> > > Thank you for your comments!
> > >
> > > On Mon, Mar 01, 2021 at 09:50:56AM +0100, Ulf Hansson wrote:
> > > > + Adrian
> > > >
> > > > On Tue, 16 Feb 2021 at 23:43, Mårten Lindahl  
> > > > wrote:
> > > > >
> > > > > Sometimes SD cards that has been run for a long time enters a state
> > > > > where it cannot by itself be recovered, but needs a power cycle to be
> > > > > operational again. Card status analysis has indicated that the card 
> > > > > can
> > > > > end up in a state where all external commands are ignored by the card
> > > > > since it is halted by data timeouts.
> > > > >
> > > > > If the card has been heavily used for a long time it can be weared 
> > > > > out,
> > > > > and should typically be replaced. But on some tests, it shows that the
> > > > > card can still be functional after a power cycle, but as it requires 
> > > > > an
> > > > > operator to do it, the card can remain in a non-operational state for 
> > > > > a
> > > > > long time until the problem has been observed by the operator.
> > > > >
> > > > > This patch adds function to power cycle the card in case it does not
> > > > > respond to a command, and then resend the command if the power cycle
> > > > > was successful. This procedure will be tested 1 time before giving up,
> > > > > and resuming host operation as normal.
> > > >
> > > > I assume the context above is all about the ioctl interface?
> > > >
> > >
> > > Yes, that's correct. The problem we have seen is triggered by ioctls.
> > >
> > > > So, when the card enters this non functional state, have you tried
> > > > just reading a block through the regular I/O interface. Does it
> > > > trigger a power cycle of the card - and then makes it functional
> > > > again?
> > > >
> > >
> > > Yes, we have tried that, and it does trigger a power cycle, making the 
> > > card
> > > operational again. But as it requires an operator to trigger it, I thought
> > > it might be something that could be automated here. At least once.
> >
> > Not sure what you mean by operator here? In the end it's a userspace
> > program running and I assume it can deal with error paths. :-)
> >
> > In any case, I understand your point.
> >
>
> Yes, we have a userspace program. So if the userspace program will try to
> restore the card in a situation such as the one we are trying to solve
> here, how shall it perform it? Is it expected that a ioctl CMD0 request
> should be enough, or is there any other support for a userspace program to
> reset the card?

Correct, there is no way for userspace to reset cards through an ioctl.

>
> If it falls on a ioctl command to reset the card, how do we handle the case
> where the ioctl times out anyway? Or is the only way for a userspace program
> to restore the card, to make a block transfer that fails?

Yes, that is what I was thinking. According to the use case you have
described, this should be possible for you to implement as a part of
your userspace program, no?

[...]

Kind regards
Uffe


Re: [PATCH v2 1/1] mmc: cqhci: fix random crash when remove mmc module

2021-03-04 Thread Ulf Hansson
On Wed, 3 Mar 2021 at 18:42, Frank Li  wrote:
>
> [ 6684.493350] Unable to handle kernel paging request at virtual address 
> 800011c5b0f0
> [ 6684.498531] mmc0: card 0001 removed
> [ 6684.501556] Mem abort info:
> [ 6684.509681]   ESR = 0x9647
> [ 6684.512786]   EC = 0x25: DABT (current EL), IL = 32 bits
> [ 6684.518394]   SET = 0, FnV = 0
> [ 6684.521707]   EA = 0, S1PTW = 0
> [ 6684.524998] Data abort info:
> [ 6684.528236]   ISV = 0, ISS = 0x0047
> [ 6684.532986]   CM = 0, WnR = 1
> [ 6684.536129] swapper pgtable: 4k pages, 48-bit VAs, pgdp=81b22000
> [ 6684.543923] [800011c5b0f0] pgd=b003, p4d=b003, 
> pud=bfffe003, pmd=900e1003, pte=
> [ 6684.557915] Internal error: Oops: 9647 [#1] PREEMPT SMP
> [ 6684.564240] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci cqhci 
> mmc_block mmc_core fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc 
> caamalg_desc crypto_engine rng_core authenc libdes crct10dif_ce flexcan 
> can_dev caam error [last unloaded: mmc_core]
> [ 6684.587281] CPU: 0 PID: 79138 Comm: kworker/0:3H Not tainted 
> 5.10.9-01410-g3ba33182767b-dirty #10
> [ 6684.596160] Hardware name: Freescale i.MX8DXL EVK (DT)
> [ 6684.601320] Workqueue: kblockd blk_mq_run_work_fn
>
> [ 6684.606094] pstate: 4005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
> [ 6684.612286] pc : cqhci_request+0x148/0x4e8 [cqhci]
> ^GMessage from syslogd@  at Thu Jan  1 01:51:24 1970 ...[ 6684.617085] lr : 
> cqhci_request+0x314/0x4e8 [cqhci]
> [ 6684.626734] sp : 80001243b9f0
> [ 6684.630049] x29: 80001243b9f0 x28: 2c3dd000
> [ 6684.635367] x27: 0001 x26: 0001
> [ 6684.640690] x25: 2c451000 x24: 000f
> [ 6684.646007] x23: 17e71c80 x22: 2c451000
> [ 6684.651326] x21: 2c0f3550 x20: 2c0f3550
> [ 6684.656651] x19: 17d46880 x18: 2cea1500
> [ 6684.661977] x17:  x16: 
> [ 6684.667294] x15: 01ee628e3ed1 x14: 0278
> [ 6684.672610] x13: 0001 x12: 0001
> [ 6684.677927] x11:  x10: 
> [ 6684.683243] x9 : 002b x8 : 1000
> [ 6684.688560] x7 : 0010 x6 : 2c0f3678
> [ 6684.693886] x5 : 000f x4 : 800011c5b000
> [ 6684.699211] x3 : 0002d988 x2 : 0008
> [ 6684.704537] x1 : 00f0 x0 : 0002d9880008102f
> [ 6684.709854] Call trace:
> [ 6684.712313]  cqhci_request+0x148/0x4e8 [cqhci]
> [ 6684.716803]  mmc_cqe_start_req+0x58/0x68 [mmc_core]
> [ 6684.721698]  mmc_blk_mq_issue_rq+0x460/0x810 [mmc_block]
> [ 6684.727018]  mmc_mq_queue_rq+0x118/0x2b0 [mmc_block]
>
> cqhci_request was called after cqhci_disable.
>
> cqhci_disable cqhci_request
> { {
> dmam_free_coherent();  (1) free
>   if(!cq_host->enable)
>return
>  (2) pass check here
> cq_host->enable = false;
>
>   task_desc= 
> get_desc(cq_host,tag);
>   crash here
>  (3) access memory which is already 
> free
>
> } }
>
> Signed-off-by: Frank Li 

Applied for fixes, thanks! I added a fixes tag and a stable tag.

Kind regards
Uffe


> ---
>
> Change from v1 to v2
>  - use Adrian Hunter suggested method to fix this problem
>
>  drivers/mmc/core/bus.c | 11 +--
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
> index c2e70b757dd1..4383c262b3f5 100644
> --- a/drivers/mmc/core/bus.c
> +++ b/drivers/mmc/core/bus.c
> @@ -399,11 +399,6 @@ void mmc_remove_card(struct mmc_card *card)
> mmc_remove_card_debugfs(card);
>  #endif
>
> -   if (host->cqe_enabled) {
> -   host->cqe_ops->cqe_disable(host);
> -   host->cqe_enabled = false;
> -   }
> -
> if (mmc_card_present(card)) {
> if (mmc_host_is_spi(card->host)) {
> pr_info("%s: SPI card removed\n",
> @@ -416,6 +411,10 @@ void mmc_remove_card(struct mmc_card *card)
> of_node_put(card->dev.of_node);
> }
>
> +   if (host->cqe_enabled) {
> +   host->cqe_ops->cqe_disable(host);
> +   host->cqe_enabled = false;
> +   }
> +
> put_device(>dev);
>  }
> -
> --
> 2.25.1
>


Re: [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap

2021-03-04 Thread Ulf Hansson
On Wed, 3 Mar 2021 at 09:32, Pradeep P V K  wrote:
>
> From: Pradeep P V K 
>
> For data read commands, SDHC may initiate data transfers even before it
> completely process the command response. In case command itself fails,
> driver un-maps the memory associated with data transfer but this memory
> can still be accessed by SDHC for the already initiated data transfer.
> This scenario can lead to un-mapped memory access error.
>
> To avoid this scenario, reset SDHC (when command fails) prior to
> un-mapping memory. Resetting SDHC ensures that all in-flight data
> transfers are either aborted or completed. So we don't run into this
> scenario.
>
> Swap the reset, un-map steps sequence in sdhci_request_done().
>
> Changes since V1:
> - Added an empty line and fixed the comment style.
> - Retained the Acked-by signoff.
>
> Suggested-by: Veerabhadrarao Badiganti 
> Signed-off-by: Pradeep P V K 
> Acked-by: Adrian Hunter 

Seems like it might be a good idea to tag this for stable? I did that,
but awaiting for your confirmation.

So, applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci.c | 60 
> +---
>  1 file changed, 31 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 646823d..130fd2d 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct sdhci_host *host)
> }
>
> /*
> +* The controller needs a reset of internal state machines
> +* upon error conditions.
> +*/
> +   if (sdhci_needs_reset(host, mrq)) {
> +   /*
> +* Do not finish until command and data lines are available 
> for
> +* reset. Note there can only be one other mrq, so it cannot
> +* also be in mrqs_done, otherwise host->cmd and 
> host->data_cmd
> +* would both be null.
> +*/
> +   if (host->cmd || host->data_cmd) {
> +   spin_unlock_irqrestore(>lock, flags);
> +   return true;
> +   }
> +
> +   /* Some controllers need this kick or reset won't work here */
> +   if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
> +   /* This is to force an update */
> +   host->ops->set_clock(host, host->clock);
> +
> +   /*
> +* Spec says we should do both at the same time, but Ricoh
> +* controllers do not like that.
> +*/
> +   sdhci_do_reset(host, SDHCI_RESET_CMD);
> +   sdhci_do_reset(host, SDHCI_RESET_DATA);
> +
> +   host->pending_reset = false;
> +   }
> +
> +   /*
>  * Always unmap the data buffers if they were mapped by
>  * sdhci_prepare_data() whenever we finish with a request.
>  * This avoids leaking DMA mappings on error.
> @@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct sdhci_host *host)
> }
> }
>
> -   /*
> -* The controller needs a reset of internal state machines
> -* upon error conditions.
> -*/
> -   if (sdhci_needs_reset(host, mrq)) {
> -   /*
> -* Do not finish until command and data lines are available 
> for
> -* reset. Note there can only be one other mrq, so it cannot
> -* also be in mrqs_done, otherwise host->cmd and 
> host->data_cmd
> -* would both be null.
> -*/
> -   if (host->cmd || host->data_cmd) {
> -   spin_unlock_irqrestore(>lock, flags);
> -   return true;
> -   }
> -
> -   /* Some controllers need this kick or reset won't work here */
> -   if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
> -   /* This is to force an update */
> -   host->ops->set_clock(host, host->clock);
> -
> -   /* Spec says we should do both at the same time, but Ricoh
> -  controllers do not like that. */
> -   sdhci_do_reset(host, SDHCI_RESET_CMD);
> -   sdhci_do_reset(host, SDHCI_RESET_DATA);
> -
> -   host->pending_reset = false;
> -   }
> -
> host->mrqs_done[i] = NULL;
>
> spin_unlock_irqrestore(>lock, flags);
> --
> 2.7.4
>


Re: [RFC PATCH 1/5] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2021-03-03 Thread Ulf Hansson
On Wed, 3 Mar 2021 at 14:55, Alex Bennée  wrote:
>
> A number of storage technologies support a specialised hardware
> partition designed to be resistant to replay attacks. The underlying
> HW protocols differ but the operations are common. The RPMB partition
> cannot be accessed via standard block layer, but by a set of specific
> commands: WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY. Such a
> partition provides authenticated and replay protected access, hence
> suitable as a secure storage.
>
> The RPMB layer aims to provide in-kernel API for Trusted Execution
> Environment (TEE) devices that are capable to securely compute block
> frame signature. In case a TEE device wishes to store a replay
> protected data, requests the storage device via RPMB layer to store
> the data.
>
> A TEE device driver can claim the RPMB interface, for example, via
> class_interface_register(). The RPMB layer provides a series of
> operations for interacting with the device.
>
>   * program_key - a one time operation for setting up a new device
>   * get_capacity - introspect the device capacity
>   * get_write_count - check the write counter
>   * write_blocks - write a series of blocks to the RPMB device
>   * read_blocks - read a series of blocks from the RPMB device
>
> The detailed operation of implementing the access is left to the TEE
> device driver itself.
>
> [This is based-on Thomas Winkler's proposed API from:
>
>   
> https://lore.kernel.org/linux-mmc/1478548394-8184-2-git-send-email-tomas.wink...@intel.com/
>
> The principle difference is the framing details and HW specific
> bits (JDEC vs NVME frames) are left to the lower level TEE driver to
> worry about. The eventual userspace ioctl interface will aim to be
> similarly generic. This is an RFC to follow up on:
>
>   Subject: RPMB user space ABI
>   Date: Thu, 11 Feb 2021 14:07:00 +
>   Message-ID: <87mtwashi4@linaro.org>]
>
> Signed-off-by: Alex Bennée 
> Cc: Tomas Winkler 
> Cc: Ulf Hansson 
> Cc: Linus  Walleij 
> Cc: Arnd Bergmann 
> Cc: Ilias Apalodimas 

Alex, I promise to have a closer look at this and provide my opinions.

However, it looks like you have posted patch 1 and patch2, but the
remainder 3, 4, 5 I can't find. Was this perhaps intentional?

Moreover, I think these kinds of changes deserve a proper
cover-letter, describing the overall goal with the series. Can you
perhaps re-submit, so clarify things.

Kind regards
Uffe

> ---
>  MAINTAINERS|   7 +
>  drivers/char/Kconfig   |   2 +
>  drivers/char/Makefile  |   1 +
>  drivers/char/rpmb/Kconfig  |  11 +
>  drivers/char/rpmb/Makefile |   7 +
>  drivers/char/rpmb/core.c   | 429 +
>  include/linux/rpmb.h   | 163 ++
>  7 files changed, 620 insertions(+)
>  create mode 100644 drivers/char/rpmb/Kconfig
>  create mode 100644 drivers/char/rpmb/Makefile
>  create mode 100644 drivers/char/rpmb/core.c
>  create mode 100644 include/linux/rpmb.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index bfc1b86e3e73..076f3983526c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15369,6 +15369,13 @@ T: git git://linuxtv.org/media_tree.git
>  F: 
> Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
>  F: drivers/media/platform/sunxi/sun8i-rotate/
>
> +RPMB SUBSYSTEM
> +M: ?
> +L: linux-kernel@vger.kernel.org
> +S: Supported
> +F: drivers/char/rpmb/*
> +F: include/linux/rpmb.h
> +
>  RTL2830 MEDIA DRIVER
>  M: Antti Palosaari 
>  L: linux-me...@vger.kernel.org
> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
> index d229a2d0c017..a7834cc3e0ea 100644
> --- a/drivers/char/Kconfig
> +++ b/drivers/char/Kconfig
> @@ -471,6 +471,8 @@ config ADI
>   and SSM (Silicon Secured Memory).  Intended consumers of this
>   driver include crash and makedumpfile.
>
> +source "drivers/char/rpmb/Kconfig"
> +
>  endmenu
>
>  config RANDOM_TRUST_CPU
> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index ffce287ef415..0eed6e21a7a7 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH)   += ps3flash.o
>  obj-$(CONFIG_XILLYBUS) += xillybus/
>  obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
>  obj-$(CONFIG_ADI)  += adi.o
> +obj-$(CONFIG_RPMB) += rpmb/
> diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
> new file mode 100644
> index ..431c2823cf70
> --- /dev/null
> +++ b/drivers/char/rpmb/Kconfig
> @@ -0,0 +1,11 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (

  1   2   3   4   5   6   7   8   9   10   >