diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 666cd2f5104e..dd4e6ac0ab25 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -84,7 +84,7 @@ #define SMEM_GLOBAL_HOST 0xfffe /* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 10 +#define SMEM_HOST_COUNT 11 /** * struct smem_proc_comm - proc_comm communication struct (legacy) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index c7300d54e444..64bb20386f24 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015, Sony Mobile Communications AB. - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2018 The Linux Foundation. All rights reserved. */ #include @@ -97,6 +97,7 @@ struct smp2p_entry { struct irq_domain *domain; DECLARE_BITMAP(irq_enabled, 32); + DECLARE_BITMAP(irq_pending, 32); DECLARE_BITMAP(irq_rising, 32); DECLARE_BITMAP(irq_falling, 32); @@ -137,6 +138,7 @@ struct qcom_smp2p { unsigned local_pid; unsigned remote_pid; + int irq; struct regmap *ipc_regmap; int ipc_offset; int ipc_bit; @@ -174,11 +176,11 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) struct smp2p_smem_item *in; struct smp2p_entry *entry; struct qcom_smp2p *smp2p = data; + unsigned long status; unsigned smem_id = smp2p->smem_items[SMP2P_INBOUND]; unsigned pid = smp2p->remote_pid; size_t size; int irq_pin; - u32 status; char buf[SMP2P_MAX_ENTRY_NAME]; u32 val; int i; @@ -219,19 +221,22 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) status = val ^ entry->last_value; entry->last_value = val; + status |= *entry->irq_pending; /* No changes of this entry? */ if (!status) continue; - for_each_set_bit(i, entry->irq_enabled, 32) { - if (!(status & BIT(i))) - continue; - + for_each_set_bit(i, &status, 32) { if ((val & BIT(i) && test_bit(i, entry->irq_rising)) || (!(val & BIT(i)) && test_bit(i, entry->irq_falling))) { irq_pin = irq_find_mapping(entry->domain, i); handle_nested_irq(irq_pin); + + if (test_bit(i, entry->irq_enabled)) + clear_bit(i, entry->irq_pending); + else + set_bit(i, entry->irq_pending); } } } @@ -293,6 +298,8 @@ static int smp2p_irq_map(struct irq_domain *d, irq_set_chip_data(irq, entry); irq_set_nested_thread(irq, 1); irq_set_noprobe(irq); + irq_set_parent(irq, entry->smp2p->irq); + irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); return 0; } @@ -444,7 +451,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev) struct device_node *node; struct qcom_smp2p *smp2p; const char *key; - int irq; int ret; smp2p = devm_kzalloc(&pdev->dev, sizeof(*smp2p), GFP_KERNEL); @@ -473,10 +479,10 @@ static int qcom_smp2p_probe(struct platform_device *pdev) if (ret) goto report_read_failure; - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + smp2p->irq = platform_get_irq(pdev, 0); + if (smp2p->irq < 0) { dev_err(&pdev->dev, "unable to acquire smp2p interrupt\n"); - return irq; + return smp2p->irq; } smp2p->mbox_client.dev = &pdev->dev; @@ -529,7 +535,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev) /* Kick the outgoing edge after allocating entries */ qcom_smp2p_kick(smp2p); - ret = devm_request_threaded_irq(&pdev->dev, irq, + ret = devm_request_threaded_irq(&pdev->dev, smp2p->irq, NULL, qcom_smp2p_intr, IRQF_ONESHOT, "smp2p", (void *)smp2p);