usb: xhci: check if 'requested segments' exceeds ERST capacity
BugLink: https://bugs.launchpad.net/bugs/2073603
[ Upstream commit db4460b6ecf07574d580f01cd88054a62607068c ]
Check if requested segments ('segs' or 'ERST_DEFAULT_SEGS') exceeds the
maximum amount ERST supports.
When 'segs' is '0', 'ERST_DEFAULT_SEGS' is used instead. But both values
may not exceed ERST max.
Macro 'ERST_MAX_SEGS' is renamed to 'ERST_DEFAULT_SEGS'. The new name
better represents the macros, which is the number of Event Ring segments
to allocate, when the amount is not specified.
Additionally, rename and change xhci_create_secondary_interrupter()'s
argument 'int num_segs' to 'unsigned int segs'. This makes it the same
as its counter part in xhci_alloc_interrupter().
Fixes: c99b38c412 ("xhci: add support to allocate several interrupters")
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240429140245.3955523-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Portia Stephens <portia.stephens@canonical.com>
Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
This commit is contained in:
committed by
Roxana Nicolescu
parent
cc64bfee92
commit
ecdc97212f
+11
-11
@@ -2280,24 +2280,24 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
|
||||
}
|
||||
|
||||
static struct xhci_interrupter *
|
||||
xhci_alloc_interrupter(struct xhci_hcd *xhci, int segs, gfp_t flags)
|
||||
xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
|
||||
{
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
|
||||
struct xhci_interrupter *ir;
|
||||
unsigned int num_segs = segs;
|
||||
unsigned int max_segs;
|
||||
int ret;
|
||||
|
||||
if (!segs)
|
||||
segs = ERST_DEFAULT_SEGS;
|
||||
|
||||
max_segs = BIT(HCS_ERST_MAX(xhci->hcs_params2));
|
||||
segs = min(segs, max_segs);
|
||||
|
||||
ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev));
|
||||
if (!ir)
|
||||
return NULL;
|
||||
|
||||
/* number of ring segments should be greater than 0 */
|
||||
if (segs <= 0)
|
||||
num_segs = min_t(unsigned int, 1 << HCS_ERST_MAX(xhci->hcs_params2),
|
||||
ERST_MAX_SEGS);
|
||||
|
||||
ir->event_ring = xhci_ring_alloc(xhci, num_segs, 1, TYPE_EVENT, 0,
|
||||
flags);
|
||||
ir->event_ring = xhci_ring_alloc(xhci, segs, 1, TYPE_EVENT, 0, flags);
|
||||
if (!ir->event_ring) {
|
||||
xhci_warn(xhci, "Failed to allocate interrupter event ring\n");
|
||||
kfree(ir);
|
||||
@@ -2355,7 +2355,7 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
|
||||
}
|
||||
|
||||
struct xhci_interrupter *
|
||||
xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg)
|
||||
xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct xhci_interrupter *ir;
|
||||
@@ -2365,7 +2365,7 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg)
|
||||
if (!xhci->interrupters || xhci->max_interrupters <= 1)
|
||||
return NULL;
|
||||
|
||||
ir = xhci_alloc_interrupter(xhci, num_seg, GFP_KERNEL);
|
||||
ir = xhci_alloc_interrupter(xhci, segs, GFP_KERNEL);
|
||||
if (!ir)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -1649,8 +1649,8 @@ struct urb_priv {
|
||||
struct xhci_td td[] __counted_by(num_tds);
|
||||
};
|
||||
|
||||
/* Reasonable limit for number of Event Ring segments (spec allows 32k) */
|
||||
#define ERST_MAX_SEGS 2
|
||||
/* Number of Event Ring segments to allocate, when amount is not specified. (spec allows 32k) */
|
||||
#define ERST_DEFAULT_SEGS 2
|
||||
/* Poll every 60 seconds */
|
||||
#define POLL_TIMEOUT 60
|
||||
/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */
|
||||
@@ -2088,7 +2088,7 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
|
||||
void xhci_free_container_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx);
|
||||
struct xhci_interrupter *
|
||||
xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg);
|
||||
xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs);
|
||||
void xhci_remove_secondary_interrupter(struct usb_hcd
|
||||
*hcd, struct xhci_interrupter *ir);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user