All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
To: Ben Widawsky <ben.widawsky@intel.com>
Cc: <linux-cxl@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-pci@vger.kernel.org>, <linux-acpi@vger.kernel.org>,
	Dan Williams <dan.j.williams@intel.com>,
	Ira Weiny <ira.weiny@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	"Kelley, Sean V" <sean.v.kelley@intel.com>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Rafael J . Wysocki" <rafael.j.wysocki@intel.com>
Subject: Re: [RFC PATCH 2/9] cxl/acpi: add OSC support
Date: Mon, 16 Nov 2020 17:59:09 +0000	[thread overview]
Message-ID: <20201116175909.00007e53@Huawei.com> (raw)
In-Reply-To: <20201111054356.793390-3-ben.widawsky@intel.com>

On Tue, 10 Nov 2020 21:43:49 -0800
Ben Widawsky <ben.widawsky@intel.com> wrote:

> From: Vishal Verma <vishal.l.verma@intel.com>
> 
> Add support to advertise OS capabilities, and request OS control for CXL
> features using the ACPI _OSC mechanism. Advertise support for all
> possible CXL features, and attempt to request control too for all
> possible features.
> 
> Based on a patch by Sean Kelley.
> 
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>

I guess unsurprisingly a lot of this is cut and paste from PCIe
so can we share some of the code?

Thanks,

Jonathan

> 
> ---
> 
> This uses a non-standard UUID for CXL and is meant as a change proposal
> to the CXL specification. The definition for _OSC intermixes PCIe and
> CXL Dwords, which makes a clean separation of CXL capabilities
> difficult, if not impossible. This is therefore subject to change.
> 
> ---
>  drivers/cxl/acpi.c | 210 ++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/cxl/acpi.h |  18 ++++
>  2 files changed, 226 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index 26e4f73838a7..c3e2f7f6ea02 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -12,6 +12,16 @@
>  #include <linux/pci.h>
>  #include "acpi.h"
>  
> +/*
> + * TODO: These are global for now to save the OSC state.
> + * This works if OSC can be expected to be uniform for every ACPI0016 object.
> + * If that is not the case, revisit this. These need to be saved because
> + * relinquishing control of a previously granted capability is disallowed.
> + */
> +static u32 cxl_osc_support_set;
> +static u32 cxl_osc_control_set;
> +static DEFINE_MUTEX(acpi_desc_lock);
> +
>  static void acpi_cxl_desc_init(struct acpi_cxl_desc *acpi_desc, struct device *dev)
>  {
>  	dev_set_drvdata(dev, acpi_desc);
> @@ -74,6 +84,199 @@ static struct acpi_driver acpi_cxl_driver = {
>  	},
>  };
>  
> +struct pci_osc_bit_struct {
> +	u32 bit;
> +	char *desc;
> +};
> +
> +static struct pci_osc_bit_struct cxl_osc_support_bit[] = {
> +	{ CXL_OSC_PORT_REG_ACCESS_SUPPORT, "CXLPortRegAccess" },
> +	{ CXL_OSC_PORT_DEV_REG_ACCESS_SUPPORT, "CXLPortDevRegAccess" },
> +	{ CXL_OSC_PER_SUPPORT, "CXLProtocolErrorReporting" },
> +	{ CXL_OSC_NATIVE_HP_SUPPORT, "CXLNativeHotPlug" },
> +};
> +
> +static struct pci_osc_bit_struct cxl_osc_control_bit[] = {
> +	{ CXL_OSC_MEM_ERROR_CONTROL, "CXLMemErrorReporting" },
> +};
> +
> +/*
> + * CXL 2.0 spec UUID - unusable as it PCI and CXL OSC are mixed
> + * static u8 cxl_osc_uuid_str[] = "68F2D50B-C469-4d8A-BD3D-941A103FD3FC";
> + */
> +/* New, proposed UUID for CXL-only OSC */
> +static u8 cxl_osc_uuid_str[] = "A4D1629D-FF52-4888-BE96-E5CADE548DB1";
> +
> +static void decode_osc_bits(struct device *dev, char *msg, u32 word,
> +			    struct pci_osc_bit_struct *table, int size)
> +{
> +	char buf[80];
> +	int i, len = 0;
> +	struct pci_osc_bit_struct *entry;
> +
> +	buf[0] = '\0';
> +	for (i = 0, entry = table; i < size; i++, entry++)
> +		if (word & entry->bit)
> +			len += scnprintf(buf + len, sizeof(buf) - len, "%s%s",
> +					len ? " " : "", entry->desc);
> +
> +	dev_info(dev, "_OSC: %s [%s]\n", msg, buf);

Can we look at sharing code with PCI?

> +}
> +
> +static void decode_cxl_osc_support(struct device *dev, char *msg, u32 word)
> +{
> +	decode_osc_bits(dev, msg, word, cxl_osc_support_bit,
> +			ARRAY_SIZE(cxl_osc_support_bit));
> +}
> +
> +static void decode_cxl_osc_control(struct device *dev, char *msg, u32 word)
> +{
> +	decode_osc_bits(dev, msg, word, cxl_osc_control_bit,
> +			ARRAY_SIZE(cxl_osc_control_bit));
> +}
> +
> +static acpi_status acpi_cap_run_osc(acpi_handle handle,
> +				    const u32 *capbuf, u8 *uuid_str, u32 *retval)
> +{
> +	struct acpi_osc_context context = {
> +		.uuid_str = uuid_str,
> +		.rev = 1,
> +		.cap.length = 20,
> +		.cap.pointer = (void *)capbuf,
> +	};
> +	acpi_status status;
> +
> +	status = acpi_run_osc(handle, &context);
> +	if (ACPI_SUCCESS(status)) {
> +		*retval = *((u32 *)(context.ret.pointer + 8));
> +		kfree(context.ret.pointer);
> +	}
> +	return status;
> +}
> +
> +static acpi_status cxl_query_osc(acpi_handle handle, u32 support, u32 *control)
> +{
> +	acpi_status status;
> +	u32 result, capbuf[5];
> +
> +	support &= CXL_OSC_SUPPORT_VALID_MASK;
> +	support |= cxl_osc_support_set;
> +
> +	capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
> +	capbuf[CXL_OSC_SUPPORT_DWORD] = support;
> +	if (control) {
> +		*control &= CXL_OSC_CONTROL_VALID_MASK;
> +		capbuf[CXL_OSC_CONTROL_DWORD] = *control | cxl_osc_control_set;
> +	} else {
> +		/* Run _OSC query only with existing controls. */
> +		capbuf[CXL_OSC_CONTROL_DWORD] = cxl_osc_control_set;
> +	}
> +
> +	status = acpi_cap_run_osc(handle, capbuf, cxl_osc_uuid_str, &result);
> +	if (ACPI_SUCCESS(status)) {
> +		cxl_osc_support_set = support;
> +		if (control)
> +			*control = result;
> +	}
> +	return status;
> +}
> +
> +static acpi_status cxl_osc_advertise_support(acpi_handle handle, u32 flags)
> +{
> +	acpi_status status;
> +
> +	mutex_lock(&acpi_desc_lock);
> +	status = cxl_query_osc(handle, flags, NULL);
> +	mutex_unlock(&acpi_desc_lock);
> +	return status;
> +}
> +
> +/**
> + * cxl_osc_request_control - Request control of CXL root _OSC features.
> + * @adev: ACPI device for the PCI root bridge (or PCIe Root Complex).
> + * @mask: Mask of _OSC bits to request control of, place to store control mask.
> + * @req: Mask of _OSC bits the control of is essential to the caller.
> + **/
> +static acpi_status cxl_osc_request_control(struct acpi_device *adev, u32 *mask, u32 req)
> +{
> +	acpi_handle handle = adev->handle;
> +	struct device *dev = &adev->dev;
> +	acpi_status status = AE_OK;
> +	u32 ctrl, capbuf[5];
> +
> +	if (!mask)
> +		return AE_BAD_PARAMETER;
> +
> +	ctrl = *mask & CXL_OSC_MEM_ERROR_CONTROL;
> +	if ((ctrl & req) != req)
> +		return AE_TYPE;
> +
> +	mutex_lock(&acpi_desc_lock);
> +
> +	*mask = ctrl | cxl_osc_control_set;
> +	/* No need to evaluate _OSC if the control was already granted. */
> +	if ((cxl_osc_control_set & ctrl) == ctrl)
> +		goto out;
> +
> +	/* Need to check the available controls bits before requesting them. */
> +	while (*mask) {
> +		status = cxl_query_osc(handle, cxl_osc_support_set, mask);
> +		if (ACPI_FAILURE(status))
> +			goto out;
> +		if (ctrl == *mask)
> +			break;
> +		decode_cxl_osc_control(dev, "platform does not support", ctrl & ~(*mask));
> +		ctrl = *mask;
> +	}
> +
> +	if ((ctrl & req) != req) {
> +		decode_cxl_osc_control(dev, "not requesting control; platform does not support",
> +				       req & ~(ctrl));
> +		status = AE_SUPPORT;
> +		goto out;
> +	}
> +
> +	capbuf[OSC_QUERY_DWORD] = 0;
> +	capbuf[CXL_OSC_SUPPORT_DWORD] = cxl_osc_support_set;
> +	capbuf[CXL_OSC_CONTROL_DWORD] = ctrl;
> +	status = acpi_cap_run_osc(handle, capbuf, cxl_osc_uuid_str, mask);
> +	if (ACPI_SUCCESS(status))
> +		cxl_osc_control_set = *mask;
> +out:
> +	mutex_unlock(&acpi_desc_lock);
> +	return status;
> +}
> +
> +static int cxl_negotiate_osc(struct acpi_device *adev)
> +{
> +	u32 cxl_support, cxl_control, requested;
> +	acpi_handle handle = adev->handle;
> +	struct device *dev = &adev->dev;
> +	acpi_status status;
> +
> +	/* Declare support for everything */
> +	cxl_support = CXL_OSC_SUPPORT_VALID_MASK;
> +	decode_cxl_osc_support(dev, "OS supports", cxl_support);
> +	status = cxl_osc_advertise_support(handle, cxl_support);
> +	if (ACPI_FAILURE(status)) {
> +		dev_info(dev, "CXL_OSC failed (%s)\n", acpi_format_exception(status));
> +		return -ENXIO;
> +	}
> +
> +	/* Request control for everything */
> +	cxl_control = CXL_OSC_CONTROL_VALID_MASK;
> +	requested = cxl_control;
> +	status = cxl_osc_request_control(adev, &cxl_control, CXL_OSC_MEM_ERROR_CONTROL);
> +	if (ACPI_SUCCESS(status)) {
> +		decode_cxl_osc_control(dev, "OS now controls", cxl_control);
> +	} else {
> +		decode_cxl_osc_control(dev, "OS requested", requested);
> +		decode_cxl_osc_control(dev, "platform willing to grant", cxl_control);
> +		dev_info(dev, "_OSC failed (%s)\n", acpi_format_exception(status));
> +	}
> +	return 0;
> +}
> +
>  /*
>   * If/when CXL support is defined by other platform firmware the kernel
>   * will need a mechanism to select between the platform specific version
> @@ -84,6 +287,7 @@ int cxl_bus_prepared(struct pci_dev *pdev)
>  	struct acpi_device *adev;
>  	struct pci_dev *root_port;
>  	struct device *root;
> +	int rc;
>  
>  	root_port = pcie_find_root_port(pdev);
>  	if (!root_port)
> @@ -97,9 +301,11 @@ int cxl_bus_prepared(struct pci_dev *pdev)
>  	if (!adev)
>  		return -ENXIO;
>  
> -	/* TODO: OSC enabling */
> +	rc = cxl_negotiate_osc(adev);
> +	if (rc)
> +		dev_err(&pdev->dev, "Failed to negotiate OSC\n");
>  
> -	return 0;
> +	return rc;
>  }
>  EXPORT_SYMBOL_GPL(cxl_bus_prepared);
>  
> diff --git a/drivers/cxl/acpi.h b/drivers/cxl/acpi.h
> index 011505475cc6..bf8d078e1b2a 100644
> --- a/drivers/cxl/acpi.h
> +++ b/drivers/cxl/acpi.h
> @@ -10,6 +10,24 @@ struct acpi_cxl_desc {
>  	struct device *dev;
>  };
>  
> +/* Indexes into _OSC Capabilities Buffer */
> +#define CXL_OSC_SUPPORT_DWORD			1	/* DWORD 2 */
> +#define CXL_OSC_CONTROL_DWORD			2	/* DWORD 3 */
> +
> +/* CXL Host Bridge _OSC: Capabilities DWORD 2: Support Field */
> +#define CXL_OSC_PORT_REG_ACCESS_SUPPORT		0x00000001
> +#define CXL_OSC_PORT_DEV_REG_ACCESS_SUPPORT	0x00000002
> +#define CXL_OSC_PER_SUPPORT			0x00000004
> +#define CXL_OSC_NATIVE_HP_SUPPORT		0x00000008
> +#define CXL_OSC_SUPPORT_VALID_MASK		(CXL_OSC_PORT_REG_ACCESS_SUPPORT |	\
> +						 CXL_OSC_PORT_DEV_REG_ACCESS_SUPPORT |	\
> +						 CXL_OSC_PER_SUPPORT |			\
> +						 CXL_OSC_NATIVE_HP_SUPPORT)
> +
> +/* CXL Host Bridge _OSC: Capabilities DWORD 3: Control Field */
> +#define CXL_OSC_MEM_ERROR_CONTROL		0x00000001
> +#define CXL_OSC_CONTROL_VALID_MASK		(CXL_OSC_MEM_ERROR_CONTROL)
> +
>  int cxl_bus_prepared(struct pci_dev *pci_dev);
>  
>  #endif	/* __CXL_ACPI_H__ */


  reply	other threads:[~2020-11-16 17:59 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-11  5:43 [RFC PATCH 0/9] CXL 2.0 Support Ben Widawsky
2020-11-11  5:43 ` [RFC PATCH 1/9] cxl/acpi: Add an acpi_cxl module for the CXL interconnect Ben Widawsky
2020-11-11  6:17   ` Randy Dunlap
2020-11-11  7:10   ` Christoph Hellwig
2020-11-11  7:30     ` Verma, Vishal L
2020-11-11  7:34       ` hch
2020-11-11  7:36         ` Verma, Vishal L
2020-11-11 23:03   ` Bjorn Helgaas
2020-11-15  4:32   ` kernel test robot
2020-11-16 17:59   ` Jonathan Cameron
2020-11-16 18:23     ` Verma, Vishal L
2020-11-17 14:32   ` Rafael J. Wysocki
2020-11-17 21:45     ` Dan Williams
2020-11-18 11:14       ` Rafael J. Wysocki
2020-11-11  5:43 ` [RFC PATCH 2/9] cxl/acpi: add OSC support Ben Widawsky
2020-11-16 17:59   ` Jonathan Cameron [this message]
2020-11-16 23:25     ` Dan Williams
2020-11-18 12:25       ` Rafael J. Wysocki
2020-11-18 17:58         ` Dan Williams
2020-11-11  5:43 ` [RFC PATCH 3/9] cxl/mem: Add a driver for the type-3 mailbox Ben Widawsky
2020-11-11  6:17   ` Randy Dunlap
2020-11-11  7:12   ` Christoph Hellwig
2020-11-11 17:17     ` Dan Williams
2020-11-11 18:27       ` Dan Williams
2020-11-11 21:41       ` Randy Dunlap
2020-11-11 22:40         ` Dan Williams
2020-11-16 16:56       ` Christoph Hellwig
2020-11-13 18:17   ` Bjorn Helgaas
2020-11-14  1:08     ` Ben Widawsky
2020-11-15  0:23       ` Dan Williams
2020-11-17 14:49   ` Jonathan Cameron
2020-12-04  7:22     ` Dan Williams
2020-12-04  7:27       ` Dan Williams
2020-12-04 17:39         ` Jonathan Cameron
2020-11-11  5:43 ` [RFC PATCH 4/9] cxl/mem: Map memory device registers Ben Widawsky
2020-11-13 18:17   ` Bjorn Helgaas
2020-11-14  1:12     ` Ben Widawsky
2020-11-16 23:19       ` Dan Williams
2020-11-17  0:23         ` Bjorn Helgaas
2020-11-23 19:20           ` Ben Widawsky
2020-11-23 19:32             ` Dan Williams
2020-11-23 19:58               ` Ben Widawsky
2020-11-17 15:00   ` Jonathan Cameron
2020-11-11  5:43 ` [RFC PATCH 5/9] cxl/mem: Find device capabilities Ben Widawsky
2020-11-13 18:26   ` Bjorn Helgaas
2020-11-14  1:36     ` Ben Widawsky
2020-11-15 11:26   ` kernel test robot
2020-11-17 15:15   ` Jonathan Cameron
2020-11-24  0:17     ` Ben Widawsky
2020-11-26  6:05   ` Jon Masters
2020-11-26 18:18     ` Ben Widawsky
2020-12-04  7:35     ` Dan Williams
2020-12-04  7:41   ` Dan Williams
2020-12-07  6:12     ` Ben Widawsky
2020-11-11  5:43 ` [RFC PATCH 6/9] cxl/mem: Initialize the mailbox interface Ben Widawsky
2020-11-17 15:22   ` Jonathan Cameron
2020-11-11  5:43 ` [RFC PATCH 7/9] cxl/mem: Implement polled mode mailbox Ben Widawsky
2020-11-13 23:14   ` Bjorn Helgaas
2020-11-17 15:31   ` Jonathan Cameron
2020-11-17 16:34     ` Ben Widawsky
2020-11-17 18:06       ` Jonathan Cameron
2020-11-17 18:38         ` Dan Williams
2020-11-11  5:43 ` [RFC PATCH 8/9] cxl/mem: Register CXL memX devices Ben Widawsky
2020-11-12  3:38   ` kernel test robot
2020-11-17 15:56   ` Jonathan Cameron
2020-11-20  2:16     ` Dan Williams
2020-11-20 15:20       ` Jonathan Cameron
2020-11-11  5:43 ` [RFC PATCH 9/9] MAINTAINERS: Add maintainers of the CXL driver Ben Widawsky
2020-11-11 22:06 ` [RFC PATCH 0/9] CXL 2.0 Support Ben Widawsky
2020-11-11 22:43 ` Bjorn Helgaas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201116175909.00007e53@Huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=ben.widawsky@intel.com \
    --cc=bhelgaas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=ira.weiny@intel.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rafael.j.wysocki@intel.com \
    --cc=sean.v.kelley@intel.com \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.