xhci rework real & fake ports
Subsystems (4)
cover xhci rework real & fake ports
This commit aims to remove the confusing real & fake port variables and improve how slot ID is found using fake port.
Clarification on real and fake ports:
- 'real port' refers to a unique hardware port number.
- 'fake_port' refers to the port number within a port hub. Its only function is to facilitate the identification of the slot ID, this process is very inefficient.
Niklas Neronin (3):
xhci: rework how real & fake ports are found
xhci: replace real & fake port with pointer to root hub port
xhci: save slot ID in struct 'xhci_port'
drivers/usb/host/xhci-hub.c | 69 ++++++--------------------------- drivers/usb/host/xhci-mem.c | 56 +++++++++++++------------- drivers/usb/host/xhci-mtk-sch.c | 14 +++---- drivers/usb/host/xhci-pci.c | 10 ++--- drivers/usb/host/xhci-ring.c | 11 ++---- drivers/usb/host/xhci-trace.h | 12 +++--- drivers/usb/host/xhci.c | 12 +++--- drivers/usb/host/xhci.h | 7 ++-- 8 files changed, 64 insertions(+), 127 deletions(-)
Signature · 1 line
2.42.0
PATCH 1/3 xhci: rework how real & fake ports are found
xHC hardware needs to know which roothub port a USB device is attached to when controlling the device, so the xHCI driver stores in each device the roothub port which it's connected behind. This is done with two different port index values, the 'real_port' which is an index to the xHC hardware port register array, and the 'fake_port' which is the per hub port index used by the hub driver.
Instead of finding real & fake port separately, find the root hub port 'xhci_port' structure which contains both real & fake port values:
- 'real_port' is equivalent to ('hw_portnum' + 1)
- 'fake_port' is equivalent to ('hcd_portnum' + 1)
i.e. real & fake port are 'hw_portnum' & 'hcd_portnum' in one-based format.
The 'xhci_port' structure is a better way to refer to roothub ports than the 'real_port' & 'fake_port'. As a result, these port indexes are slated to be replaced with a direct pointer to the root hub port. This patch setups the ground work for the future changes.
--- drivers/usb/host/xhci-mem.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-)
drivers/usb/host/xhci-mem.c +15 -19
@@ -1050,16 +1050,16 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,* The xHCI roothub may have ports of differing speeds in any order in the port * status registers. * -* The xHCI hardware wants to know the roothub port number that the USB device +* The xHCI hardware wants to know the roothub port that the USB device * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status -* registers. Call xhci_find_raw_port_number() to get real index. +* registers. */ -static u32 xhci_find_real_port_number (struct xhci_hcd *xhci, -struct usb_device *udev) +static struct xhci_port *xhci_find_rhub_port (struct xhci_hcd *xhci,struct usb_device *udev) {struct usb_device *top_dev; +struct xhci_hub *rhub;struct usb_hcd *hcd;if (udev->speed >=USB_SPEED_SUPER )
@@ -1071,7 +1071,8 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, top_dev = top_dev->parent)/* Found device below root hub */ ; -return xhci_find_raw_port_number (hcd, top_dev->portnum); + rhub =xhci_get_rhub (hcd); +return rhub->ports[top_dev->portnum -1 ]; }/* Setup an xHCI virtual device for a Set Address command */
@@ -1080,9 +1081,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udstruct xhci_virt_device *dev;struct xhci_ep_ctx *ep0_ctx;struct xhci_slot_ctx *slot_ctx; -u32 port_num; +struct xhci_port *rhub_port;u32 max_packets; -struct usb_device *top_dev; dev = xhci->devs[udev->slot_id];/* Slot ID 0 is reserved */
@@ -1123,17 +1123,13 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udreturn -EINVAL ; }/* Find the root hub port this device is under */ - port_num =xhci_find_real_port_number (xhci, udev); -if (!port_num) + rhub_port =xhci_find_rhub_port (xhci, udev); +if (!rhub_port)return -EINVAL ; - slot_ctx->dev_info2 |=cpu_to_le32 (ROOT_HUB_PORT (port_num)); -/* Set the port number in the virtual_device to the faked port number */ -for (top_dev = udev; top_dev->parent && top_dev->parent->parent; - top_dev = top_dev->parent) -/* Found device below root hub */ ; - dev->fake_port = top_dev->portnum; - dev->real_port = port_num; -xhci_dbg (xhci,"Set root hub portnum to %d\n" , port_num); + dev->real_port = rhub_port->hw_portnum +1 ; + dev->fake_port = rhub_port->hcd_portnum +1 ; + slot_ctx->dev_info2 |=cpu_to_le32 (ROOT_HUB_PORT (dev->real_port)); +xhci_dbg (xhci,"Set root hub portnum to %d\n" , dev->real_port);xhci_dbg (xhci,"Set fake root hub portnum to %d\n" , dev->fake_port);/* Find the right bandwidth table that this device will be a part of.
@@ -1143,12 +1139,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud* will never be created for the HS root hub. */ if (!udev->tt || !udev->tt->hub->parent) { - dev->bw_table = &xhci->rh_bw[port_num -1 ].bw_table; + dev->bw_table = &xhci->rh_bw[dev->real_port -1 ].bw_table; }else {struct xhci_root_port_bw_info *rh_bw;struct xhci_tt_bw_info *tt_bw; - rh_bw = &xhci->rh_bw[port_num -1 ]; + rh_bw = &xhci->rh_bw[dev->real_port -1 ];/* Find the right TT. */ list_for_each_entry (tt_bw, &rh_bw->tts, tt_list) {if (tt_bw->slot_id != udev->tt->hub->slot_id)
Signature · 1 line
2.42.0
PATCH 2/3 xhci: replace real & fake port with pointer to root hub port
In reply to Niklas NeroninVariables real & fake port lacked explicitness in their purpose, leading to confusion. Thus, they are replaced with a pointer to the root hub port struct xhci_port: '*rhub_port'.
'rhub_port' contains both the 'real' and 'fake' ports in a zero-based format, which happens to be more widely used inside the xHCI driver. To elaborate:
- 'real_port' corresponds to ('rhub_port->hw_portnum' + 1)
- 'fake_port' corresponds to ('rhub_port->hcd_portnum' + 1)
One reason for real port being one-based, is to signal other functions in case struct 'xhci_virt_device' initialization failed, in this case the value will remain 0. This is no longer needed, instead we check whether or not 'rhub_port' is 'NULL'.
--- drivers/usb/host/xhci-hub.c | 4 +++- drivers/usb/host/xhci-mem.c | 35 ++++++++++++++------------------- drivers/usb/host/xhci-mtk-sch.c | 14 +++++-------- drivers/usb/host/xhci-trace.h | 12 +++++------ drivers/usb/host/xhci.c | 12 +++++------ drivers/usb/host/xhci.h | 3 +-- 6 files changed, 35 insertions(+), 45 deletions(-)
drivers/usb/host/xhci-hub.c +3 -1
@@ -464,13 +464,15 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,int i;enum usb_device_speed speed; +/* 'hcd_portnum' is zero-based, thus convert one-based 'port' to zero-based */ + port -=1 ; slot_id =0 ;for (i =0 ; i <MAX_HC_SLOTS ; i++) {if (!xhci->devs[i] || !xhci->devs[i]->udev)continue ; speed = xhci->devs[i]->udev->speed;if (((speed >=USB_SPEED_SUPER ) == (hcd->speed >=HCD_USB3 )) - && xhci->devs[i]->fake_port == port) { + && xhci->devs[i]->rhub_port->hcd_portnum == port) { slot_id = i;break ; }
drivers/usb/host/xhci-mem.c +15 -20
@@ -788,15 +788,14 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci,bool slot_found = false;/* If the device never made it past the Set Address stage, -* it may not have the real_port set correctly. +* it may not have the root hub port pointer set correctly. */ -if (virt_dev->real_port ==0 || - virt_dev->real_port >HCS_MAX_PORTS (xhci->hcs_params1)) { -xhci_dbg (xhci,"Bad real port.\n" ); +if (!virt_dev->rhub_port) { +xhci_dbg (xhci,"Bad rhub port.\n" );return ; } - tt_list_head = &(xhci->rh_bw[virt_dev->real_port -1 ].tts); + tt_list_head = &(xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts);list_for_each_entry_safe (tt_info, next, tt_list_head, tt_list) {/* Multi-TT hubs will have more than one entry */ if (tt_info->slot_id == slot_id) {
@@ -833,7 +832,7 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, goto free_tts;INIT_LIST_HEAD (&tt_info->tt_list);list_add (&tt_info->tt_list, - &xhci->rh_bw[virt_dev->real_port -1 ].tts); + &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts); tt_info->slot_id = virt_dev->udev->slot_id;if (tt->multi) tt_info->ttport = i+1 ;
@@ -928,13 +927,12 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_iif (!vdev)return ; -if (vdev->real_port ==0 || - vdev->real_port >HCS_MAX_PORTS (xhci->hcs_params1)) { -xhci_dbg (xhci,"Bad vdev->real_port.\n" ); +if (!vdev->rhub_port) { +xhci_dbg (xhci,"Bad rhub port.\n" ); goto out; } - tt_list_head = &(xhci->rh_bw[vdev->real_port -1 ].tts); + tt_list_head = &(xhci->rh_bw[vdev->rhub_port->hw_portnum].tts);list_for_each_entry_safe (tt_info, next, tt_list_head, tt_list) {/* is this a hub device that added a tt_info to the tts list */ if (tt_info->slot_id == slot_id) {
@@ -1081,7 +1079,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udstruct xhci_virt_device *dev;struct xhci_ep_ctx *ep0_ctx;struct xhci_slot_ctx *slot_ctx; -struct xhci_port *rhub_port;u32 max_packets; dev = xhci->devs[udev->slot_id];
@@ -1123,14 +1120,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udreturn -EINVAL ; }/* Find the root hub port this device is under */ - rhub_port =xhci_find_rhub_port (xhci, udev); -if (!rhub_port) + dev->rhub_port =xhci_find_rhub_port (xhci, udev); +if (!dev->rhub_port)return -EINVAL ; - dev->real_port = rhub_port->hw_portnum +1 ; - dev->fake_port = rhub_port->hcd_portnum +1 ; - slot_ctx->dev_info2 |=cpu_to_le32 (ROOT_HUB_PORT (dev->real_port)); -xhci_dbg (xhci,"Set root hub portnum to %d\n" , dev->real_port); -xhci_dbg (xhci,"Set fake root hub portnum to %d\n" , dev->fake_port); + slot_ctx->dev_info2 |=cpu_to_le32 (ROOT_HUB_PORT (dev->rhub_port->hw_portnum +1 )); +xhci_dbg (xhci,"Slot ID %d: HW portnum %d, hcd portnum %d\n" , + udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum);/* Find the right bandwidth table that this device will be a part of. * If this is a full speed device attached directly to a root port (or a
@@ -1139,12 +1134,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud* will never be created for the HS root hub. */ if (!udev->tt || !udev->tt->hub->parent) { - dev->bw_table = &xhci->rh_bw[dev->real_port -1 ].bw_table; + dev->bw_table = &xhci->rh_bw[dev->rhub_port->hw_portnum].bw_table; }else {struct xhci_root_port_bw_info *rh_bw;struct xhci_tt_bw_info *tt_bw; - rh_bw = &xhci->rh_bw[dev->real_port -1 ]; + rh_bw = &xhci->rh_bw[dev->rhub_port->hw_portnum];/* Find the right TT. */ list_for_each_entry (tt_bw, &rh_bw->tts, tt_list) {if (tt_bw->slot_id != udev->tt->hub->slot_id)
drivers/usb/host/xhci-mtk-sch.c +5 -9
@@ -122,10 +122,6 @@ static u32 get_bw_boundary(enum usb_device_speed speed)* each HS root port is treated as a single bandwidth domain, * but each SS root port is treated as two bandwidth domains, one for IN eps, * one for OUT eps. -* @real_port value is defined as follow according to xHCI spec: -* 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc -* so the bandwidth domain array is organized as follow for simplification: -* SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY */ static struct mu3h_sch_bw_info * get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
@@ -136,19 +132,19 @@ get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,int bw_index; virt_dev = xhci->devs[udev->slot_id]; -if (!virt_dev->real_port) { -WARN_ONCE (1 ,"%s invalid real_port\n" ,dev_name (&udev->dev)); +if (!virt_dev->rhub_port) { +WARN_ONCE (1 ,"%s invalid rhub port\n" ,dev_name (&udev->dev));return NULL ; }if (udev->speed >=USB_SPEED_SUPER ) {if (usb_endpoint_dir_out (&ep->desc)) - bw_index = (virt_dev->real_port -1 ) *2 ; + bw_index = (virt_dev->rhub_port->hw_portnum) *2 ;else - bw_index = (virt_dev->real_port -1 ) *2 +1 ; + bw_index = (virt_dev->rhub_port->hw_portnum) *2 +1 ; }else {/* add one more for each SS port */ - bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports -1 ; + bw_index = virt_dev->rhub_port->hw_portnum + xhci->usb3_rhub.num_ports; }return &mtk->sch_array[bw_index];
drivers/usb/host/xhci-trace.h +6 -6
@@ -172,8 +172,8 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __field(void *, vdev) __field(unsigned long long, out_ctx) __field(unsigned long long, in_ctx) - __field(u8, fake_port) - __field(u8, real_port) + __field(int, hcd_portnum) + __field(int, hw_portnum) __field(u16, current_mel) ),
@@ -181,13 +181,13 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __entry->vdev = vdev; __entry->in_ctx = (unsigned long long ) vdev->in_ctx->dma; __entry->out_ctx = (unsigned long long ) vdev->out_ctx->dma; - __entry->fake_port = (u8 ) vdev->fake_port; - __entry->real_port = (u8 ) vdev->real_port; + __entry->hcd_portnum = (int ) vdev->rhub_port->hcd_portnum; + __entry->hw_portnum = (int ) vdev->rhub_port->hw_portnum; __entry->current_mel = (u16 ) vdev->current_mel; ), -TP_printk ("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d" , +TP_printk ("vdev %p ctx %llx | %llx hcd_portnum %d hw_portnum %d current_mel %d" , __entry->vdev, __entry->in_ctx, __entry->out_ctx, - __entry->fake_port, __entry->real_port, __entry->current_mel + __entry->hcd_portnum, __entry->hw_portnum, __entry->current_mel ) );
drivers/usb/host/xhci.c +5 -7
@@ -2254,7 +2254,7 @@ static int xhci_check_tt_bw_table(struct xhci_hcd *xhci,struct xhci_tt_bw_info *tt_info;/* Find the bandwidth table for the root port this TT is attached to. */ - bw_table = &xhci->rh_bw[virt_dev->real_port -1 ].bw_table; + bw_table = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].bw_table; tt_info = virt_dev->tt_info;/* If this TT already had active endpoints, the bandwidth for this TT * has already been added. Removing all periodic endpoints (and thus
@@ -2372,7 +2372,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci,if (virt_dev->tt_info) {xhci_dbg_trace (xhci, trace_xhci_dbg_quirks,"Recalculating BW for rootport %u" , - virt_dev->real_port); + virt_dev->rhub_port->hw_portnum +1 );if (xhci_check_tt_bw_table (xhci, virt_dev, old_active_eps)) {xhci_warn (xhci,"Not enough bandwidth on HS bus for " "newly activated TT.\n" );
@@ -2385,7 +2385,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, }else {xhci_dbg_trace (xhci, trace_xhci_dbg_quirks,"Recalculating BW for rootport %u" , - virt_dev->real_port); + virt_dev->rhub_port->hw_portnum +1 ); }/* Add in how much bandwidth will be used for interval zero, or the
@@ -2482,14 +2482,12 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, bw_used += overhead + packet_size;if (!virt_dev->tt_info && virt_dev->udev->speed ==USB_SPEED_HIGH ) { -unsigned int port_index = virt_dev->real_port -1 ; -/* OK, we're manipulating a HS device attached to a * root port bandwidth domain. Include the number of active TTs * in the bandwidth used. */ bw_used +=TT_HS_OVERHEAD * - xhci->rh_bw[port_index].num_active_tts; + xhci->rh_bw[virt_dev->rhub_port->hw_portnum].num_active_tts; } xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
@@ -2676,7 +2674,7 @@ void xhci_update_tt_active_eps(struct xhci_hcd *xhci,if (!virt_dev->tt_info)return ; - rh_bw_info = &xhci->rh_bw[virt_dev->real_port -1 ]; + rh_bw_info = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum];if (old_active_eps ==0 && virt_dev->tt_info->active_eps !=0 ) { rh_bw_info->num_active_tts +=1 ;
drivers/usb/host/xhci.h +1 -2
@@ -993,8 +993,7 @@ struct xhci_virt_device {/* Used for addressing devices and configuration changes */ struct xhci_container_ctx *in_ctx;struct xhci_virt_ep eps[EP_CTX_PER_DEV ]; -u8 fake_port; -u8 real_port; +struct xhci_port *rhub_port;struct xhci_interval_bw_table *bw_table;struct xhci_tt_bw_info *tt_info;/*
Signature · 1 line
2.42.0
PATCH 3/3 xhci: save slot ID in struct 'xhci_port'
In reply to Niklas NeroninSlot ID is a index of a virtual device in struct 'xhci_hcd->devs[]'. Previously, to get the slot ID assosiated with a port, we had to loop through all devices and compare ports, which is very inefficient. Instead, the slot ID (of the device which is directly connected to the port), is added to the its corresponding 'xhci_port' struct. As a result, finding the port's device is quick and easy.
Function 'xhci_find_slot_id_by_port()' is removed, as it is no longer needed.
--- drivers/usb/host/xhci-hub.c | 71 ++++++------------------------------ drivers/usb/host/xhci-mem.c | 5 +++ drivers/usb/host/xhci-pci.c | 10 ++--- drivers/usb/host/xhci-ring.c | 11 ++---- drivers/usb/host/xhci.h | 4 +- 5 files changed, 26 insertions(+), 75 deletions(-)
drivers/usb/host/xhci-hub.c +11 -60
@@ -448,40 +448,6 @@ u32 xhci_port_state_to_neutral(u32 state) }EXPORT_SYMBOL_GPL (xhci_port_state_to_neutral); -/** -* xhci_find_slot_id_by_port() - Find slot id of a usb device on a roothub port -* @hcd: pointer to hcd of the roothub -* @xhci: pointer to xhci structure -* @port: one-based port number of the port in this roothub. -* -* Return: Slot id of the usb device connected to the root port, 0 if not found -*/ - -int xhci_find_slot_id_by_port (struct usb_hcd *hcd,struct xhci_hcd *xhci, -u16 port) -{ -int slot_id; -int i; -enum usb_device_speed speed; - -/* 'hcd_portnum' is zero-based, thus convert one-based 'port' to zero-based */ - port -=1 ; - slot_id =0 ; -for (i =0 ; i <MAX_HC_SLOTS ; i++) { -if (!xhci->devs[i] || !xhci->devs[i]->udev) -continue ; - speed = xhci->devs[i]->udev->speed; -if (((speed >=USB_SPEED_SUPER ) == (hcd->speed >=HCD_USB3 )) - && xhci->devs[i]->rhub_port->hcd_portnum == port) { - slot_id = i; -break ; - } - } - -return slot_id; -} -EXPORT_SYMBOL_GPL (xhci_find_slot_id_by_port); -/* * Stop device * It issues stop endpoint command for EP 0 to 30. And wait the last command
@@ -932,7 +898,6 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,struct xhci_bus_state *bus_state;struct xhci_hcd *xhci;struct usb_hcd *hcd; -int slot_id;u32 wIndex; hcd = port->rhub->hcd;
@@ -988,13 +953,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,spin_lock_irqsave (&xhci->lock, *flags);if (time_left) { - slot_id =xhci_find_slot_id_by_port (hcd, xhci, - wIndex +1 ); -if (!slot_id) { +if (!port->slot_id) {xhci_dbg (xhci,"slot_id is zero\n" );return -ENODEV ; } -xhci_ring_device (xhci, slot_id); +xhci_ring_device (xhci, port->slot_id); }else {int port_status =readl (port->addr);
@@ -1204,7 +1167,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,unsigned long flags;u32 temp, status;int retval =0 ; -int slot_id;struct xhci_bus_state *bus_state;u16 link_state =0 ;u16 wake_mask =0 ;
@@ -1334,15 +1296,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; } - slot_id =xhci_find_slot_id_by_port (hcd, xhci, - portnum1); -if (!slot_id) { +if (!port->slot_id) {xhci_warn (xhci,"slot_id is zero\n" ); goto error; }/* unlock to execute stop endpoint commands */ spin_unlock_irqrestore (&xhci->lock, flags); -xhci_stop_device (xhci, slot_id,1 ); +xhci_stop_device (xhci, port->slot_id,1 );spin_lock_irqsave (&xhci->lock, flags);xhci_set_link_state (xhci, port,XDEV_U3 );
@@ -1465,14 +1425,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,if (link_state ==USB_SS_PORT_LS_U3 ) {int retries =16 ; - slot_id =xhci_find_slot_id_by_port (hcd, xhci, - portnum1); -if (slot_id) { +if (port->slot_id) {/* unlock to execute stop endpoint * commands */ spin_unlock_irqrestore (&xhci->lock, flags); -xhci_stop_device (xhci, slot_id,1 ); +xhci_stop_device (xhci, port->slot_id,1 );spin_lock_irqsave (&xhci->lock, flags); }xhci_set_link_state (xhci, port,USB_SS_PORT_LS_U3 );
@@ -1586,13 +1544,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } bus_state->port_c_suspend |=1 << wIndex; - slot_id =xhci_find_slot_id_by_port (hcd, xhci, - portnum1); -if (!slot_id) { +if (!port->slot_id) {xhci_dbg (xhci,"slot_id is zero\n" ); goto error; } -xhci_ring_device (xhci, slot_id); +xhci_ring_device (xhci, port->slot_id);break ;case USB_PORT_FEAT_C_SUSPEND : bus_state->port_c_suspend &= ~(1 << wIndex);
@@ -1823,10 +1779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)if (!portsc_buf[port_index])continue ;if (test_bit (port_index, &bus_state->bus_suspended)) { -int slot_id; - - slot_id =xhci_find_slot_id_by_port (hcd, xhci, - port_index +1 ); +int slot_id = ports[port_index]->slot_id;if (slot_id) {spin_unlock_irqrestore (&xhci->lock, flags);xhci_stop_device (xhci, slot_id,1 );
@@ -1879,7 +1832,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)struct xhci_bus_state *bus_state;unsigned long flags;int max_ports, port_index; -int slot_id;int sret;u32 next_state;u32 temp, portsc;
@@ -1972,9 +1924,8 @@ int xhci_bus_resume(struct usb_hcd *hcd)continue ; }xhci_test_and_clear_bit (xhci, ports[port_index],PORT_PLC ); - slot_id =xhci_find_slot_id_by_port (hcd, xhci, port_index +1 ); -if (slot_id) -xhci_ring_device (xhci, slot_id); +if (ports[port_index]->slot_id) +xhci_ring_device (xhci, ports[port_index]->slot_id); } (void )readl (&xhci->op_regs->command);
drivers/usb/host/xhci-mem.c +5 -0
@@ -906,6 +906,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)if (dev->udev && dev->udev->slot_id) dev->udev->slot_id =0 ; +if (dev->rhub_port && dev->rhub_port->slot_id == slot_id) + dev->rhub_port->slot_id =0 ;kfree (xhci->devs[slot_id]); xhci->devs[slot_id] =NULL ; }
@@ -1123,6 +1125,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud dev->rhub_port =xhci_find_rhub_port (xhci, udev);if (!dev->rhub_port)return -EINVAL ; +/* Slot ID is set to the device directly below the root hub */ +if (!udev->parent->parent) + dev->rhub_port->slot_id = udev->slot_id; slot_ctx->dev_info2 |=cpu_to_le32 (ROOT_HUB_PORT (dev->rhub_port->hw_portnum +1 ));xhci_dbg (xhci,"Slot ID %d: HW portnum %d, hcd portnum %d\n" , udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum);
drivers/usb/host/xhci-pci.c +4 -6
@@ -884,7 +884,6 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)struct xhci_hcd *xhci =hcd_to_xhci (hcd);struct xhci_port *port;struct usb_device *udev; -unsigned int slot_id;u32 portsc;int i;
@@ -907,15 +906,14 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)if ((portsc &PORT_PLS_MASK ) !=XDEV_U3 )continue ; - slot_id =xhci_find_slot_id_by_port (port->rhub->hcd, xhci, - port->hcd_portnum +1 ); -if (!slot_id || !xhci->devs[slot_id]) { +if (!port->slot_id || !xhci->devs[port->slot_id]) {xhci_err (xhci,"No dev for slot_id %d for port %d-%d in U3\n" , - slot_id, port->rhub->hcd->self.busnum, port->hcd_portnum +1 ); + port->slot_id, port->rhub->hcd->self.busnum, + port->hcd_portnum +1 );continue ; } - udev = xhci->devs[slot_id]->udev; + udev = xhci->devs[port->slot_id]->udev;/* if wakeup is enabled then don't disable the port */ if (udev->do_remote_wakeup && do_wakeup)
drivers/usb/host/xhci-ring.c +4 -7
@@ -1863,7 +1863,6 @@ static void handle_port_status(struct xhci_hcd *xhci,u32 port_id;u32 portsc, cmd_reg;int max_ports; -int slot_id;unsigned int hcd_portnum;struct xhci_bus_state *bus_state;bool bogus_port_status = false;
@@ -1915,9 +1914,8 @@ static void handle_port_status(struct xhci_hcd *xhci,if (hcd->speed >=HCD_USB3 && (portsc &PORT_PLS_MASK ) ==XDEV_INACTIVE ) { - slot_id =xhci_find_slot_id_by_port (hcd, xhci, hcd_portnum +1 ); -if (slot_id && xhci->devs[slot_id]) - xhci->devs[slot_id]->flags |=VDEV_PORT_ERROR ; +if (port->slot_id && xhci->devs[port->slot_id]) + xhci->devs[port->slot_id]->flags |=VDEV_PORT_ERROR ; }if ((portsc &PORT_PLC ) && (portsc &PORT_PLS_MASK ) ==XDEV_RESUME ) {
@@ -1975,9 +1973,8 @@ static void handle_port_status(struct xhci_hcd *xhci,* so the roothub behavior is consistent with external * USB 3.0 hub behavior. */ - slot_id =xhci_find_slot_id_by_port (hcd, xhci, hcd_portnum +1 ); -if (slot_id && xhci->devs[slot_id]) -xhci_ring_device (xhci, slot_id); +if (port->slot_id && xhci->devs[port->slot_id]) +xhci_ring_device (xhci, port->slot_id);if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {xhci_test_and_clear_bit (xhci, port,PORT_PLC ); usb_wakeup_notification(hcd->self.root_hub,
drivers/usb/host/xhci.h +2 -2
@@ -1710,6 +1710,8 @@ struct xhci_port { unsigned int lpm_incapable:1;unsigned long resume_timestamp;bool rexit_active; +/* Slot ID is the index of the device directly connected to the port */ +int slot_id;struct completion rexit_done;struct completion u3exit_done; };
@@ -2189,8 +2191,6 @@ unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd);#endif /* CONFIG_PM */ u32 xhci_port_state_to_neutral (u32 state); -int xhci_find_slot_id_by_port (struct usb_hcd *hcd,struct xhci_hcd *xhci, -u16 port);void xhci_ring_device (struct xhci_hcd *xhci,int slot_id);/* xHCI contexts */
Signature · 1 line
2.42.0