Unverified Commit a224ad7b authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!8576 【OLK-6.6】backport PCC patches to support shared interrupt for multiple...

!8576 【OLK-6.6】backport PCC patches to support shared interrupt for multiple subspaces and platform notification handling

Merge Pull Request from: @huangdengdui 
 
1bd4ab6e4d11 mailbox: pcc: Support shared interrupt for multiple subspaces
08436163fa34 mailbox: pcc: Add support for platform notification handling
95d6333e0622 soc: hisilicon: kunpeng_hccs: replace MAILBOX dependency with PCC
192f97fe164d soc: hisilicon: kunpeng_hccs: Add the check for obtaining complete port attribute 
 
Link:https://gitee.com/openeuler/kernel/pulls/8576

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 429b54bc b2d9c364
Loading
Loading
Loading
Loading
+80 −11
Original line number Diff line number Diff line
@@ -91,6 +91,14 @@ struct pcc_chan_reg {
 * @cmd_update: PCC register bundle for the command complete update register
 * @error: PCC register bundle for the error status register
 * @plat_irq: platform interrupt
 * @type: PCC subspace type
 * @plat_irq_flags: platform interrupt flags
 * @chan_in_use: this flag is used just to check if the interrupt needs
 *		handling when it is shared. Since only one transfer can occur
 *		at a time and mailbox takes care of locking, this flag can be
 *		accessed without a lock. Note: the type only support the
 *		communication from OSPM to Platform, like type3, use it, and
 *		other types completely ignore it.
 */
struct pcc_chan_info {
	struct pcc_mbox_chan chan;
@@ -100,12 +108,17 @@ struct pcc_chan_info {
	struct pcc_chan_reg cmd_update;
	struct pcc_chan_reg error;
	int plat_irq;
	u8 type;
	unsigned int plat_irq_flags;
	bool chan_in_use;
};

#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
static struct pcc_chan_info *chan_info;
static int pcc_chan_count;

static int pcc_send_data(struct mbox_chan *chan, void *data);

/*
 * PCC can be used with perf critical drivers such as CPPC
 * So it makes sense to locally cache the virtual address and
@@ -221,6 +234,41 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags)
	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
}

static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan)
{
	return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) ==
		ACPI_LEVEL_SENSITIVE;
}

static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
{
	u64 val;
	int ret;

	ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
	if (ret)
		return false;

	if (!pchan->cmd_complete.gas)
		return true;

	/*
	 * Judge if the channel respond the interrupt based on the value of
	 * command complete.
	 */
	val &= pchan->cmd_complete.status_mask;

	/*
	 * If this is PCC slave subspace channel, and the command complete
	 * bit 0 indicates that Platform is sending a notification and OSPM
	 * needs to respond this interrupt to process this command.
	 */
	if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
		return !val;

	return !!val;
}

/**
 * pcc_mbox_irq - PCC mailbox interrupt handler
 * @irq:	interrupt number
@@ -236,16 +284,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
	int ret;

	pchan = chan->con_priv;

	ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
	if (ret)
	if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE &&
	    !pchan->chan_in_use)
		return IRQ_NONE;

	if (val) { /* Ensure GAS exists and value is non-zero */
		val &= pchan->cmd_complete.status_mask;
		if (!val)
	if (!pcc_mbox_cmd_complete_check(pchan))
		return IRQ_NONE;
	}

	ret = pcc_chan_reg_read(&pchan->error, &val);
	if (ret)
@@ -262,6 +306,16 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)

	mbox_chan_received_data(chan, NULL);

	/*
	 * The PCC slave subspace channel needs to set the command complete bit
	 * and ring doorbell after processing message.
	 *
	 * The PCC master subspace channel clears chan_in_use to free channel.
	 */
	if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
		pcc_send_data(chan, NULL);
	pchan->chan_in_use = false;

	return IRQ_HANDLED;
}

@@ -340,7 +394,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
	if (ret)
		return ret;

	return pcc_chan_reg_read_modify_write(&pchan->db);
	ret = pcc_chan_reg_read_modify_write(&pchan->db);
	if (!ret && pchan->plat_irq > 0)
		pchan->chan_in_use = true;

	return ret;
}

/**
@@ -353,11 +411,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
static int pcc_startup(struct mbox_chan *chan)
{
	struct pcc_chan_info *pchan = chan->con_priv;
	unsigned long irqflags;
	int rc;

	if (pchan->plat_irq > 0) {
		rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0,
				      MBOX_IRQ_NAME, chan);
		irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ?
						IRQF_SHARED | IRQF_ONESHOT : 0;
		rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq,
				      irqflags, MBOX_IRQ_NAME, chan);
		if (unlikely(rc)) {
			dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n",
				pchan->plat_irq);
@@ -463,6 +524,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
		       pcct_ss->platform_interrupt);
		return -EINVAL;
	}
	pchan->plat_irq_flags = pcct_ss->flags;

	if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
		struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;
@@ -484,6 +546,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
					"PLAT IRQ ACK");
	}

	if (pcc_chan_plat_irq_can_be_shared(pchan) &&
	    !pchan->plat_irq_ack.gas) {
		pr_err("PCC subspace has level IRQ with no ACK register\n");
		return -EINVAL;
	}

	return ret;
}

@@ -698,6 +766,7 @@ static int pcc_mbox_probe(struct platform_device *pdev)

		pcc_parse_subspace_shmem(pchan, pcct_entry);

		pchan->type = pcct_entry->type;
		pcct_entry = (struct acpi_subtable_header *)
			((unsigned long) pcct_entry + pcct_entry->length);
	}
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ config HISI_HBMDEV_ACLS
config KUNPENG_HCCS
	tristate "HCCS driver on Kunpeng SoC"
	depends on ACPI
	depends on MAILBOX
	depends on PCC
	depends on ARM64 || COMPILE_TEST
	help
	  The Huawei Cache Coherence System (HCCS) is a multi-chip
+6 −0
Original line number Diff line number Diff line
@@ -556,6 +556,12 @@ static int hccs_get_all_port_attr(struct hccs_dev *hdev,
		start_id = rsp_head.next_id;
	}

	if (left_buf_len != 0) {
		dev_err(hdev->dev, "failed to get the expected port number(%u) attribute.\n",
			size);
		return -EINVAL;
	}

	return 0;
}