Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: usb-acpi: Set port connect type of not connectable ports correctly

Ports with _UPC (USB Port Capability) ACPI objects stating they are
"not connectable" are not wired to any connector or internal device.
They only exist inside the host controller.

These ports may not have an ACPI _PLD (Physical Location of Device)
object.

Rework the code so that _UPC is read even if _PLD does not exist, and
make sure the port->connect_type is set to "USB_PORT_NOT_USED" instead
of "USB_PORT_CONNECT_TYPE_UNKNOWN".

No bugs or known issues are reported due to possibly not parsing _UPC,
and thus leaving the port connect type as "unknown" instead of
"not used". Nice to have this fixed but no need to add it to stable
kernels, or urgency to get it upstream.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240223140305.185182-1-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
f3ac348e 41717b88

+23 -23
+23 -23
drivers/usb/core/usb-acpi.c
··· 142 142 } 143 143 EXPORT_SYMBOL_GPL(usb_acpi_set_power_state); 144 144 145 - static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle, 146 - struct acpi_pld_info *pld) 145 + /* 146 + * Private to usb-acpi, all the core needs to know is that 147 + * port_dev->location is non-zero when it has been set by the firmware. 148 + */ 149 + #define USB_ACPI_LOCATION_VALID (1 << 31) 150 + 151 + static void 152 + usb_acpi_get_connect_type(struct usb_port *port_dev, acpi_handle *handle) 147 153 { 148 154 enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN; 149 155 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 150 156 union acpi_object *upc = NULL; 157 + struct acpi_pld_info *pld; 151 158 acpi_status status; 152 159 153 160 /* ··· 165 158 * a usb device is directly hard-wired to the port. If no visible and 166 159 * no connectable, the port would be not used. 167 160 */ 161 + 162 + status = acpi_get_physical_device_location(handle, &pld); 163 + if (ACPI_SUCCESS(status) && pld) 164 + port_dev->location = USB_ACPI_LOCATION_VALID | 165 + pld->group_token << 8 | pld->group_position; 166 + 168 167 status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer); 169 168 if (ACPI_FAILURE(status)) 170 169 goto out; ··· 179 166 if (!upc || (upc->type != ACPI_TYPE_PACKAGE) || upc->package.count != 4) 180 167 goto out; 181 168 169 + /* UPC states port is connectable */ 182 170 if (upc->package.elements[0].integer.value) 183 - if (pld->user_visible) 171 + if (!pld) 172 + ; /* keep connect_type as unknown */ 173 + else if (pld->user_visible) 184 174 connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG; 185 175 else 186 176 connect_type = USB_PORT_CONNECT_TYPE_HARD_WIRED; 187 - else if (!pld->user_visible) 177 + else 188 178 connect_type = USB_PORT_NOT_USED; 189 179 out: 180 + port_dev->connect_type = connect_type; 190 181 kfree(upc); 191 - return connect_type; 182 + ACPI_FREE(pld); 192 183 } 193 - 194 - 195 - /* 196 - * Private to usb-acpi, all the core needs to know is that 197 - * port_dev->location is non-zero when it has been set by the firmware. 198 - */ 199 - #define USB_ACPI_LOCATION_VALID (1 << 31) 200 184 201 185 static struct acpi_device * 202 186 usb_acpi_get_companion_for_port(struct usb_port *port_dev) ··· 232 222 usb_acpi_find_companion_for_port(struct usb_port *port_dev) 233 223 { 234 224 struct acpi_device *adev; 235 - struct acpi_pld_info *pld; 236 - acpi_handle *handle; 237 - acpi_status status; 238 225 239 226 adev = usb_acpi_get_companion_for_port(port_dev); 240 227 if (!adev) 241 228 return NULL; 242 229 243 - handle = adev->handle; 244 - status = acpi_get_physical_device_location(handle, &pld); 245 - if (ACPI_SUCCESS(status) && pld) { 246 - port_dev->location = USB_ACPI_LOCATION_VALID 247 - | pld->group_token << 8 | pld->group_position; 248 - port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); 249 - ACPI_FREE(pld); 250 - } 230 + usb_acpi_get_connect_type(port_dev, adev->handle); 251 231 252 232 return adev; 253 233 }