xhci: replace real & fake port with pointer to root hub port

Variables real & fake port do not convey their purpose, thus they are
replaced with a pointer to the root hub port 'struct xhci_port *rhub_port'.
'rhub_port' contains real & fake ports in zero-based format, which happens
to be more widely used inside the xHCI driver:
 - 'real_port' is ('rhub_port->hw_portnum' + 1)
 - 'fake_port' is ('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'.

Signed-off-by: Niklas Neronin <niklas.neronin@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240229141438.619372-3-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Niklas Neronin 2024-02-29 16:14:31 +02:00 committed by Greg Kroah-Hartman
parent c9a63ec5d2
commit 06790c1908
6 changed files with 35 additions and 45 deletions

View File

@ -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;
}

View File

@ -789,15 +789,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) {
@ -834,7 +833,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;
@ -929,13 +928,12 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
if (!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) {
@ -1082,7 +1080,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
struct 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];
@ -1124,14 +1121,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
return -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
@ -1140,12 +1135,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)

View File

@ -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];

View File

@ -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
)
);

View File

@ -2273,7 +2273,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
@ -2391,7 +2391,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");
@ -2404,7 +2404,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
@ -2501,14 +2501,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,
@ -2695,7 +2693,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;

View File

@ -739,8 +739,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;
/*