Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6cfde07c authored by Chunfeng Yun's avatar Chunfeng Yun Committed by Greg Kroah-Hartman
Browse files

usb: xhci-mtk: add some schedule error number



[ Upstream commit ccda8c224c0701caac007311d06a2de9543a7590 ]

This is used to provide more information about which case
causes bandwidth schedule failure.

Signed-off-by: default avatarChunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/9771f44093053b581e9c4be4b7fb68d9fcecad08.1615170625.git.chunfeng.yun@mediatek.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 548011957d1d ("usb: xhci-mtk: relax TT periodic bandwidth allocation")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 664b0b8f
Loading
Loading
Loading
Loading
+35 −9
Original line number Diff line number Diff line
@@ -25,6 +25,13 @@
 */
#define TT_MICROFRAMES_MAX 9

/* schedule error type */
#define ESCH_SS_Y6		1001
#define ESCH_SS_OVERLAP		1002
#define ESCH_CS_OVERFLOW	1003
#define ESCH_BW_OVERFLOW	1004
#define ESCH_FIXME		1005

/* mtk scheduler bitmasks */
#define EP_BPKTS(p)	((p) & 0x7f)
#define EP_BCSCOUNT(p)	(((p) & 0x7) << 8)
@@ -32,6 +39,24 @@
#define EP_BOFFSET(p)	((p) & 0x3fff)
#define EP_BREPEAT(p)	(((p) & 0x7fff) << 16)

static char *sch_error_string(int err_num)
{
	switch (err_num) {
	case ESCH_SS_Y6:
		return "Can't schedule Start-Split in Y6";
	case ESCH_SS_OVERLAP:
		return "Can't find a suitable Start-Split location";
	case ESCH_CS_OVERFLOW:
		return "The last Complete-Split is greater than 7";
	case ESCH_BW_OVERFLOW:
		return "Bandwidth exceeds the maximum limit";
	case ESCH_FIXME:
		return "FIXME, to be resolved";
	default:
		return "Unknown";
	}
}

static int is_fs_or_ls(enum usb_device_speed speed)
{
	return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
@@ -395,7 +420,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
		for (j = 0; j < sch_ep->cs_count; j++) {
			tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe;
			if (tmp > FS_PAYLOAD_MAX)
				return -ERANGE;
				return -ESCH_BW_OVERFLOW;
		}
	}

@@ -421,11 +446,11 @@ static int check_sch_tt(struct usb_device *udev,
		 * must never schedule Start-Split in Y6
		 */
		if (!(start_ss == 7 || last_ss < 6))
			return -ERANGE;
			return -ESCH_SS_Y6;

		for (i = 0; i < sch_ep->cs_count; i++)
			if (test_bit(offset + i, tt->ss_bit_map))
				return -ERANGE;
				return -ESCH_SS_OVERLAP;

	} else {
		u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
@@ -435,14 +460,14 @@ static int check_sch_tt(struct usb_device *udev,
		 * must never schedule Start-Split in Y6
		 */
		if (start_ss == 6)
			return -ERANGE;
			return -ESCH_SS_Y6;

		/* one uframe for ss + one uframe for idle */
		start_cs = (start_ss + 2) % 8;
		last_cs = start_cs + cs_count - 1;

		if (last_cs > 7)
			return -ERANGE;
			return -ESCH_CS_OVERFLOW;

		if (sch_ep->ep_type == ISOC_IN_EP)
			extra_cs_count = (last_cs == 7) ? 1 : 2;
@@ -454,7 +479,7 @@ static int check_sch_tt(struct usb_device *udev,
			cs_count = 7; /* HW limit */

		if (test_bit(offset, tt->ss_bit_map))
			return -ERANGE;
			return -ESCH_SS_OVERLAP;

		sch_ep->cs_count = cs_count;
		/* one for ss, the other for idle */
@@ -547,7 +572,7 @@ static int check_sch_bw(struct usb_device *udev,
	u32 esit_boundary;
	u32 min_num_budget;
	u32 min_cs_count;
	int ret;
	int ret = 0;

	/*
	 * Search through all possible schedule microframes.
@@ -588,7 +613,7 @@ static int check_sch_bw(struct usb_device *udev,

	/* check bandwidth */
	if (min_bw > bw_boundary)
		return -ERANGE;
		return ret ? ret : -ESCH_BW_OVERFLOW;

	sch_ep->offset = min_index;
	sch_ep->cs_count = min_cs_count;
@@ -765,7 +790,8 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)

		ret = check_sch_bw(udev, sch_bw, sch_ep);
		if (ret) {
			xhci_err(xhci, "Not enough bandwidth!\n");
			xhci_err(xhci, "Not enough bandwidth! (%s)\n",
				 sch_error_string(-ret));
			return -ENOSPC;
		}
	}