Message ID | 20210126155723.9388-6-mika.westerberg@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | thunderbolt / ACPI: Add support for USB4 _OSC | expand |
On Tue, Jan 26, 2021 at 5:01 PM Mika Westerberg <mika.westerberg@linux.intel.com> wrote: > > ACPI 6.4 introduced a new _OSC capability that is used negotiate native > connection manager support. Connection manager is the entity that is > responsible for tunneling over the USB4 fabric. If the platform rejects > the native access then firmware based connection manager is used. > > The new _OSC also includes a set of bits that can be used to disable > certain tunnel types such as PCIe for security reasons for instance. > > This implements the new USB4 _OSC so that we try to negotiate native > USB4 support if the Thunderbolt/USB4 (CONFIG_USB4) driver is enabled. > Drivers can determine what was negotiated by checking two new variables > exposed in this patch. > > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> > --- > drivers/acpi/bus.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/acpi.h | 10 ++++++ > 2 files changed, 86 insertions(+) > > diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c > index ca7c7b2bf56e..f7ad2d283e51 100644 > --- a/drivers/acpi/bus.c > +++ b/drivers/acpi/bus.c > @@ -281,6 +281,12 @@ bool osc_sb_apei_support_acked; > bool osc_pc_lpi_support_confirmed; > EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed); > > +/* > + * ACPI 6.4 Operating System Capabilities for USB. > + */ > +bool osc_sb_native_usb4_support_confirmed; > +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed); > + > static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; > static void acpi_bus_osc_negotiate_platform_control(void) > { > @@ -317,6 +323,9 @@ static void acpi_bus_osc_negotiate_platform_control(void) > if (IS_ENABLED(CONFIG_SCHED_MC_PRIO)) > capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT; > > + if (IS_ENABLED(CONFIG_USB4)) > + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT; > + > if (!ghes_disable) > capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; > if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) > @@ -348,8 +357,74 @@ static void acpi_bus_osc_negotiate_platform_control(void) > capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; > osc_pc_lpi_support_confirmed = > capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; > + osc_sb_native_usb4_support_confirmed = > + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT; > + } > + > + kfree(context.ret.pointer); > +} > + > +/* > + * Native control of USB4 capabilities. If any of the tunneling bits is > + * set it means OS is in control and we use software based connection > + * manager. > + */ > +u32 osc_sb_native_usb4_control; > +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control); > + > +static void acpi_bus_decode_usb_osc(const char *msg, u32 bits) > +{ > + printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg, > + (bits & OSC_USB_USB3_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_DP_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_XDOMAIN) ? '+' : '-'); > +} > + > +static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A"; > +static void acpi_bus_osc_negotiate_usb_control(void) > +{ > + u32 capbuf[3]; > + struct acpi_osc_context context = { > + .uuid_str = sb_usb_uuid_str, > + .rev = 1, > + .cap.length = sizeof(capbuf), > + .cap.pointer = capbuf, > + }; > + acpi_handle handle; > + acpi_status status; > + u32 control; > + > + if (!osc_sb_native_usb4_support_confirmed) > + return; > + > + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) > + return; > + > + control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING | > + OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN; > + > + capbuf[OSC_QUERY_DWORD] = 0; > + capbuf[OSC_SUPPORT_DWORD] = 0; > + capbuf[OSC_CONTROL_DWORD] = control; > + > + status = acpi_run_osc(handle, &context); This is the same _OSC that is evaluated in acpi_bus_osc_negotiate_platform_control(), right? So shouldn't the capbuf[OSC_SUPPORT_DWORD] be whatever is negotiated through acpi_bus_osc_negotiate_platform_control()? At least that would be consistent with acpi_pci_osc_control_set(). And if this was done I'm not sure if the change in the previous patch would be needed then? > + if (ACPI_FAILURE(status)) > + return; > + > + if (context.ret.length != sizeof(capbuf)) { > + printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n"); > + goto out_free; > } > > + osc_sb_native_usb4_control = > + control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD]; > + > + acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control); > + acpi_bus_decode_usb_osc("USB4 _OSC: OS controls", > + osc_sb_native_usb4_control); > + > +out_free: > kfree(context.ret.pointer); > } > > @@ -1188,6 +1263,7 @@ static int __init acpi_bus_init(void) > * so it must be run after ACPI_FULL_INITIALIZATION > */ > acpi_bus_osc_negotiate_platform_control(); > + acpi_bus_osc_negotiate_usb_control(); > > /* > * _PDC control method may load dynamic SSDT tables, > diff --git a/include/linux/acpi.h b/include/linux/acpi.h > index 2630c2e953f7..ac68c2d4e393 100644 > --- a/include/linux/acpi.h > +++ b/include/linux/acpi.h > @@ -546,9 +546,19 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); > #define OSC_SB_OSLPI_SUPPORT 0x00000100 > #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 > #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 > +#define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 > > extern bool osc_sb_apei_support_acked; > extern bool osc_pc_lpi_support_confirmed; > +extern bool osc_sb_native_usb4_support_confirmed; > + > +/* USB4 Capabilities */ > +#define OSC_USB_USB3_TUNNELING 0x00000001 > +#define OSC_USB_DP_TUNNELING 0x00000002 > +#define OSC_USB_PCIE_TUNNELING 0x00000004 > +#define OSC_USB_XDOMAIN 0x00000008 > + > +extern u32 osc_sb_native_usb4_control; > > /* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */ > #define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001 > -- > 2.29.2 >
Hi, On Tue, Jan 26, 2021 at 06:35:20PM +0100, Rafael J. Wysocki wrote: > > + capbuf[OSC_QUERY_DWORD] = 0; > > + capbuf[OSC_SUPPORT_DWORD] = 0; > > + capbuf[OSC_CONTROL_DWORD] = control; > > + > > + status = acpi_run_osc(handle, &context); > > This is the same _OSC that is evaluated in > acpi_bus_osc_negotiate_platform_control(), right? Yes, but different UUID. > So shouldn't the capbuf[OSC_SUPPORT_DWORD] be whatever is negotiated > through acpi_bus_osc_negotiate_platform_control()? At least that > would be consistent with acpi_pci_osc_control_set(). The ACPI 6.4 spec says that the support field for this _OSC is reserved (table 6.14 in the spec). So as far as I can tell this is not the same as what we pass for the platform _OSC.
On Tue, Jan 26, 2021 at 6:46 PM Mika Westerberg <mika.westerberg@linux.intel.com> wrote: > > Hi, > > On Tue, Jan 26, 2021 at 06:35:20PM +0100, Rafael J. Wysocki wrote: > > > + capbuf[OSC_QUERY_DWORD] = 0; > > > + capbuf[OSC_SUPPORT_DWORD] = 0; > > > + capbuf[OSC_CONTROL_DWORD] = control; > > > + > > > + status = acpi_run_osc(handle, &context); > > > > This is the same _OSC that is evaluated in > > acpi_bus_osc_negotiate_platform_control(), right? > > Yes, but different UUID. I've missed that, sorry for the noise.
On Tue, Jan 26, 2021 at 5:01 PM Mika Westerberg <mika.westerberg@linux.intel.com> wrote: > > ACPI 6.4 introduced a new _OSC capability that is used negotiate native > connection manager support. Connection manager is the entity that is > responsible for tunneling over the USB4 fabric. If the platform rejects > the native access then firmware based connection manager is used. > > The new _OSC also includes a set of bits that can be used to disable > certain tunnel types such as PCIe for security reasons for instance. > > This implements the new USB4 _OSC so that we try to negotiate native > USB4 support if the Thunderbolt/USB4 (CONFIG_USB4) driver is enabled. > Drivers can determine what was negotiated by checking two new variables > exposed in this patch. > > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/bus.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/acpi.h | 10 ++++++ > 2 files changed, 86 insertions(+) > > diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c > index ca7c7b2bf56e..f7ad2d283e51 100644 > --- a/drivers/acpi/bus.c > +++ b/drivers/acpi/bus.c > @@ -281,6 +281,12 @@ bool osc_sb_apei_support_acked; > bool osc_pc_lpi_support_confirmed; > EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed); > > +/* > + * ACPI 6.4 Operating System Capabilities for USB. > + */ > +bool osc_sb_native_usb4_support_confirmed; > +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed); > + > static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; > static void acpi_bus_osc_negotiate_platform_control(void) > { > @@ -317,6 +323,9 @@ static void acpi_bus_osc_negotiate_platform_control(void) > if (IS_ENABLED(CONFIG_SCHED_MC_PRIO)) > capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT; > > + if (IS_ENABLED(CONFIG_USB4)) > + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT; > + > if (!ghes_disable) > capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; > if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) > @@ -348,8 +357,74 @@ static void acpi_bus_osc_negotiate_platform_control(void) > capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; > osc_pc_lpi_support_confirmed = > capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; > + osc_sb_native_usb4_support_confirmed = > + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT; > + } > + > + kfree(context.ret.pointer); > +} > + > +/* > + * Native control of USB4 capabilities. If any of the tunneling bits is > + * set it means OS is in control and we use software based connection > + * manager. > + */ > +u32 osc_sb_native_usb4_control; > +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control); > + > +static void acpi_bus_decode_usb_osc(const char *msg, u32 bits) > +{ > + printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg, > + (bits & OSC_USB_USB3_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_DP_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-', > + (bits & OSC_USB_XDOMAIN) ? '+' : '-'); > +} > + > +static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A"; > +static void acpi_bus_osc_negotiate_usb_control(void) > +{ > + u32 capbuf[3]; > + struct acpi_osc_context context = { > + .uuid_str = sb_usb_uuid_str, > + .rev = 1, > + .cap.length = sizeof(capbuf), > + .cap.pointer = capbuf, > + }; > + acpi_handle handle; > + acpi_status status; > + u32 control; > + > + if (!osc_sb_native_usb4_support_confirmed) > + return; > + > + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) > + return; > + > + control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING | > + OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN; > + > + capbuf[OSC_QUERY_DWORD] = 0; > + capbuf[OSC_SUPPORT_DWORD] = 0; > + capbuf[OSC_CONTROL_DWORD] = control; > + > + status = acpi_run_osc(handle, &context); > + if (ACPI_FAILURE(status)) > + return; > + > + if (context.ret.length != sizeof(capbuf)) { > + printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n"); > + goto out_free; > } > > + osc_sb_native_usb4_control = > + control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD]; > + > + acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control); > + acpi_bus_decode_usb_osc("USB4 _OSC: OS controls", > + osc_sb_native_usb4_control); > + > +out_free: > kfree(context.ret.pointer); > } > > @@ -1188,6 +1263,7 @@ static int __init acpi_bus_init(void) > * so it must be run after ACPI_FULL_INITIALIZATION > */ > acpi_bus_osc_negotiate_platform_control(); > + acpi_bus_osc_negotiate_usb_control(); > > /* > * _PDC control method may load dynamic SSDT tables, > diff --git a/include/linux/acpi.h b/include/linux/acpi.h > index 2630c2e953f7..ac68c2d4e393 100644 > --- a/include/linux/acpi.h > +++ b/include/linux/acpi.h > @@ -546,9 +546,19 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); > #define OSC_SB_OSLPI_SUPPORT 0x00000100 > #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 > #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 > +#define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 > > extern bool osc_sb_apei_support_acked; > extern bool osc_pc_lpi_support_confirmed; > +extern bool osc_sb_native_usb4_support_confirmed; > + > +/* USB4 Capabilities */ > +#define OSC_USB_USB3_TUNNELING 0x00000001 > +#define OSC_USB_DP_TUNNELING 0x00000002 > +#define OSC_USB_PCIE_TUNNELING 0x00000004 > +#define OSC_USB_XDOMAIN 0x00000008 > + > +extern u32 osc_sb_native_usb4_control; > > /* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */ > #define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001 > -- > 2.29.2 >
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ca7c7b2bf56e..f7ad2d283e51 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -281,6 +281,12 @@ bool osc_sb_apei_support_acked; bool osc_pc_lpi_support_confirmed; EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed); +/* + * ACPI 6.4 Operating System Capabilities for USB. + */ +bool osc_sb_native_usb4_support_confirmed; +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed); + static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; static void acpi_bus_osc_negotiate_platform_control(void) { @@ -317,6 +323,9 @@ static void acpi_bus_osc_negotiate_platform_control(void) if (IS_ENABLED(CONFIG_SCHED_MC_PRIO)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT; + if (IS_ENABLED(CONFIG_USB4)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT; + if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) @@ -348,8 +357,74 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; osc_pc_lpi_support_confirmed = capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; + osc_sb_native_usb4_support_confirmed = + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT; + } + + kfree(context.ret.pointer); +} + +/* + * Native control of USB4 capabilities. If any of the tunneling bits is + * set it means OS is in control and we use software based connection + * manager. + */ +u32 osc_sb_native_usb4_control; +EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control); + +static void acpi_bus_decode_usb_osc(const char *msg, u32 bits) +{ + printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg, + (bits & OSC_USB_USB3_TUNNELING) ? '+' : '-', + (bits & OSC_USB_DP_TUNNELING) ? '+' : '-', + (bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-', + (bits & OSC_USB_XDOMAIN) ? '+' : '-'); +} + +static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A"; +static void acpi_bus_osc_negotiate_usb_control(void) +{ + u32 capbuf[3]; + struct acpi_osc_context context = { + .uuid_str = sb_usb_uuid_str, + .rev = 1, + .cap.length = sizeof(capbuf), + .cap.pointer = capbuf, + }; + acpi_handle handle; + acpi_status status; + u32 control; + + if (!osc_sb_native_usb4_support_confirmed) + return; + + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) + return; + + control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING | + OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN; + + capbuf[OSC_QUERY_DWORD] = 0; + capbuf[OSC_SUPPORT_DWORD] = 0; + capbuf[OSC_CONTROL_DWORD] = control; + + status = acpi_run_osc(handle, &context); + if (ACPI_FAILURE(status)) + return; + + if (context.ret.length != sizeof(capbuf)) { + printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n"); + goto out_free; } + osc_sb_native_usb4_control = + control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD]; + + acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control); + acpi_bus_decode_usb_osc("USB4 _OSC: OS controls", + osc_sb_native_usb4_control); + +out_free: kfree(context.ret.pointer); } @@ -1188,6 +1263,7 @@ static int __init acpi_bus_init(void) * so it must be run after ACPI_FULL_INITIALIZATION */ acpi_bus_osc_negotiate_platform_control(); + acpi_bus_osc_negotiate_usb_control(); /* * _PDC control method may load dynamic SSDT tables, diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 2630c2e953f7..ac68c2d4e393 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -546,9 +546,19 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 +#define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 extern bool osc_sb_apei_support_acked; extern bool osc_pc_lpi_support_confirmed; +extern bool osc_sb_native_usb4_support_confirmed; + +/* USB4 Capabilities */ +#define OSC_USB_USB3_TUNNELING 0x00000001 +#define OSC_USB_DP_TUNNELING 0x00000002 +#define OSC_USB_PCIE_TUNNELING 0x00000004 +#define OSC_USB_XDOMAIN 0x00000008 + +extern u32 osc_sb_native_usb4_control; /* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */ #define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001
ACPI 6.4 introduced a new _OSC capability that is used negotiate native connection manager support. Connection manager is the entity that is responsible for tunneling over the USB4 fabric. If the platform rejects the native access then firmware based connection manager is used. The new _OSC also includes a set of bits that can be used to disable certain tunnel types such as PCIe for security reasons for instance. This implements the new USB4 _OSC so that we try to negotiate native USB4 support if the Thunderbolt/USB4 (CONFIG_USB4) driver is enabled. Drivers can determine what was negotiated by checking two new variables exposed in this patch. Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> --- drivers/acpi/bus.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 10 ++++++ 2 files changed, 86 insertions(+)