kernel: add uvc debug patch
This commit is contained in:
parent
8855f9ab78
commit
48dfe4bae7
@ -20,6 +20,11 @@ PKGBUILD_REPO=${LESAVKA_KERNEL_PKG_REPO:-https://github.com/archlinuxarm/PKGBUIL
|
||||
BUILD_ROOT=${LESAVKA_KERNEL_BUILD_ROOT:-/var/tmp/lesavka-linux-rpi}
|
||||
PKGREL=${LESAVKA_KERNEL_PKGREL:-2}
|
||||
JOBS=${LESAVKA_KERNEL_JOBS:-2}
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
PATCH_DIR=${LESAVKA_KERNEL_PATCH_DIR:-$SCRIPT_DIR}
|
||||
PATCH_DWC2_FIFO=${LESAVKA_KERNEL_PATCH_DWC2_FIFO:-}
|
||||
PATCH_UVC_BULK=${LESAVKA_KERNEL_PATCH_UVC_BULK:-}
|
||||
PATCH_UVC_DEBUG=${LESAVKA_KERNEL_PATCH_UVC_DEBUG:-}
|
||||
|
||||
HEARTBEAT=/etc/lesavka/watchdog.touch
|
||||
if [[ -w $HEARTBEAT && -z ${LESAVKA_DISABLE_KEEPALIVE:-} ]]; then
|
||||
@ -94,10 +99,69 @@ for line in sums:
|
||||
pkgbuild.write_text(text)
|
||||
PY
|
||||
|
||||
MAKEPKG_EXTRA=""
|
||||
KERNEL_SRC="$BUILD_ROOT/linux-rpi/src/linux-$KERNEL_COMMIT"
|
||||
PATCHES=()
|
||||
if [[ -n $PATCH_DWC2_FIFO ]]; then
|
||||
PATCHES+=("dwc2-fifo.patch")
|
||||
fi
|
||||
if [[ -n $PATCH_UVC_BULK ]]; then
|
||||
PATCHES+=("uvc-bulk.patch")
|
||||
fi
|
||||
if [[ -n $PATCH_UVC_DEBUG ]]; then
|
||||
PATCHES+=("uvc-debug.patch")
|
||||
fi
|
||||
if [[ ${#PATCHES[@]} -gt 0 ]]; then
|
||||
sudo -u "$BUILD_USER" bash -c "
|
||||
set -euo pipefail
|
||||
cd '$BUILD_ROOT/linux-rpi'
|
||||
MAKEFLAGS='-j$JOBS' makepkg -s --noconfirm
|
||||
MAKEFLAGS='-j$JOBS' makepkg -o --noconfirm
|
||||
"
|
||||
sudo -u "$BUILD_USER" bash -c "
|
||||
set -euo pipefail
|
||||
src='$KERNEL_SRC'
|
||||
if [[ ! -d \$src ]]; then
|
||||
echo \"missing kernel source \$src\" >&2
|
||||
exit 1
|
||||
fi
|
||||
cd \"\$src\"
|
||||
for patch in ${PATCHES[*]}; do
|
||||
patch_file='$PATCH_DIR/'\"\$patch\"
|
||||
if [[ ! -f \$patch_file ]]; then
|
||||
echo \"missing patch \$patch_file\" >&2
|
||||
exit 1
|
||||
fi
|
||||
case \"\$patch\" in
|
||||
dwc2-fifo.patch)
|
||||
if grep -q 'dwc2_check_param_fifo_total' \"drivers/usb/dwc2/params.c\"; then
|
||||
echo \"dwc2-fifo patch already applied\"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
uvc-bulk.patch)
|
||||
if grep -q 'streaming_bulk' \"drivers/usb/gadget/function/uvc_configfs.c\"; then
|
||||
echo \"uvc-bulk patch already applied\"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
uvc-debug.patch)
|
||||
if grep -q 'uvcg_video_enable: missing uvc/func/config' \
|
||||
\"drivers/usb/gadget/function/uvc_video.c\"; then
|
||||
echo \"uvc-debug patch already applied\"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
patch -p1 < \"\$patch_file\"
|
||||
done
|
||||
"
|
||||
MAKEPKG_EXTRA="-e"
|
||||
fi
|
||||
|
||||
sudo -u "$BUILD_USER" bash -c "
|
||||
set -euo pipefail
|
||||
cd '$BUILD_ROOT/linux-rpi'
|
||||
MAKEFLAGS='-j$JOBS' makepkg -s --noconfirm $MAKEPKG_EXTRA
|
||||
"
|
||||
|
||||
mapfile -t PKGS < <(ls "$BUILD_ROOT/linux-rpi"/*.pkg.tar.* 2>/dev/null)
|
||||
|
||||
68
scripts/kernel/dwc2-fifo.patch
Normal file
68
scripts/kernel/dwc2-fifo.patch
Normal file
@ -0,0 +1,68 @@
|
||||
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
|
||||
index 0a10aa2f8f5c..d7c5a3d1c4de 100644
|
||||
--- a/drivers/usb/dwc2/gadget.c
|
||||
+++ b/drivers/usb/dwc2/gadget.c
|
||||
@@ -226,10 +226,7 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int addr;
|
||||
int tx_addr_max;
|
||||
- u32 np_tx_fifo_size;
|
||||
-
|
||||
- np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size,
|
||||
- hsotg->params.g_np_tx_fifo_size);
|
||||
+ u32 np_tx_fifo_size = hsotg->params.g_np_tx_fifo_size;
|
||||
|
||||
/* Get Endpoint Info Control block size in DWORDs. */
|
||||
tx_addr_max = hsotg->hw_params.total_fifo_size;
|
||||
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
|
||||
index 5d29c2157fbe..b25f7399b41c 100644
|
||||
--- a/drivers/usb/dwc2/params.c
|
||||
+++ b/drivers/usb/dwc2/params.c
|
||||
@@ -767,6 +767,35 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
|
||||
}
|
||||
}
|
||||
|
||||
+static void dwc2_check_param_fifo_total(struct dwc2_hsotg *hsotg)
|
||||
+{
|
||||
+ struct dwc2_core_params *p = &hsotg->params;
|
||||
+ u32 total_tx = 0;
|
||||
+ u32 max_np;
|
||||
+ int fifo_count;
|
||||
+ int fifo;
|
||||
+
|
||||
+ fifo_count = dwc2_hsotg_tx_fifo_count(hsotg);
|
||||
+ for (fifo = 1; fifo <= fifo_count; fifo++)
|
||||
+ total_tx += p->g_tx_fifo_size[fifo];
|
||||
+
|
||||
+ if (p->g_rx_fifo_size + p->g_np_tx_fifo_size + total_tx <=
|
||||
+ hsotg->hw_params.total_fifo_size)
|
||||
+ return;
|
||||
+
|
||||
+ max_np = 16;
|
||||
+ if (hsotg->hw_params.total_fifo_size > p->g_rx_fifo_size + total_tx)
|
||||
+ max_np = hsotg->hw_params.total_fifo_size -
|
||||
+ p->g_rx_fifo_size - total_tx;
|
||||
+ if (max_np < 16)
|
||||
+ max_np = 16;
|
||||
+
|
||||
+ dev_warn(hsotg->dev,
|
||||
+ "%s: FIFO sizes exceed total, clamping g_np_tx_fifo_size to %u\n",
|
||||
+ __func__, max_np);
|
||||
+ p->g_np_tx_fifo_size = max_np;
|
||||
+}
|
||||
+
|
||||
static void dwc2_check_param_eusb2_disc(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 gsnpsid;
|
||||
@@ -879,9 +879,10 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
|
||||
CHECK_RANGE(g_rx_fifo_size,
|
||||
16, hw->rx_fifo_size,
|
||||
hw->rx_fifo_size);
|
||||
CHECK_RANGE(g_np_tx_fifo_size,
|
||||
- 16, hw->dev_nperio_tx_fifo_size,
|
||||
+ 16, hw->total_fifo_size,
|
||||
hw->dev_nperio_tx_fifo_size);
|
||||
dwc2_check_param_tx_fifo_sizes(hsotg);
|
||||
+ dwc2_check_param_fifo_total(hsotg);
|
||||
}
|
||||
}
|
||||
173
scripts/kernel/uvc-bulk.patch
Normal file
173
scripts/kernel/uvc-bulk.patch
Normal file
@ -0,0 +1,173 @@
|
||||
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
|
||||
index aa6ab666741a..7fb30b09e980 100644
|
||||
--- a/drivers/usb/gadget/function/f_uvc.c
|
||||
+++ b/drivers/usb/gadget/function/f_uvc.c
|
||||
@@ -652,22 +652,32 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
unsigned int max_packet_size;
|
||||
struct usb_ep *ep;
|
||||
struct f_uvc_opts *opts;
|
||||
+ bool bulk;
|
||||
int ret = -EINVAL;
|
||||
|
||||
uvcg_info(f, "%s()\n", __func__);
|
||||
|
||||
opts = fi_to_f_uvc_opts(f->fi);
|
||||
+ bulk = opts->streaming_bulk;
|
||||
/* Sanity check the streaming endpoint module parameters. */
|
||||
opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U);
|
||||
- opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
|
||||
opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
|
||||
|
||||
- /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */
|
||||
- if (opts->streaming_maxburst &&
|
||||
- (opts->streaming_maxpacket % 1024) != 0) {
|
||||
- opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
|
||||
- uvcg_info(f, "overriding streaming_maxpacket to %d\n",
|
||||
- opts->streaming_maxpacket);
|
||||
+ if (bulk) {
|
||||
+ opts->streaming_maxpacket =
|
||||
+ clamp(opts->streaming_maxpacket, 1U, 1024U);
|
||||
+ } else {
|
||||
+ opts->streaming_maxpacket =
|
||||
+ clamp(opts->streaming_maxpacket, 1U, 3072U);
|
||||
+ /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */
|
||||
+ if (opts->streaming_maxburst &&
|
||||
+ (opts->streaming_maxpacket % 1024) != 0) {
|
||||
+ opts->streaming_maxpacket =
|
||||
+ roundup(opts->streaming_maxpacket, 1024);
|
||||
+ uvcg_info(f,
|
||||
+ "overriding streaming_maxpacket to %d\n",
|
||||
+ opts->streaming_maxpacket);
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -677,37 +687,70 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
* NOTE: We assume that the user knows what they are doing and won't
|
||||
* give parameters that their UDC doesn't support.
|
||||
*/
|
||||
- if (opts->streaming_maxpacket <= 1024) {
|
||||
+ if (bulk) {
|
||||
max_packet_mult = 1;
|
||||
max_packet_size = opts->streaming_maxpacket;
|
||||
- } else if (opts->streaming_maxpacket <= 2048) {
|
||||
- max_packet_mult = 2;
|
||||
- max_packet_size = opts->streaming_maxpacket / 2;
|
||||
- } else {
|
||||
- max_packet_mult = 3;
|
||||
- max_packet_size = opts->streaming_maxpacket / 3;
|
||||
- }
|
||||
|
||||
- uvc_fs_streaming_ep.wMaxPacketSize =
|
||||
- cpu_to_le16(min(opts->streaming_maxpacket, 1023U));
|
||||
- uvc_fs_streaming_ep.bInterval = opts->streaming_interval;
|
||||
+ uvc_fs_streaming_ep.bmAttributes = USB_ENDPOINT_XFER_BULK;
|
||||
+ uvc_hs_streaming_ep.bmAttributes = USB_ENDPOINT_XFER_BULK;
|
||||
+ uvc_ss_streaming_ep.bmAttributes = USB_ENDPOINT_XFER_BULK;
|
||||
|
||||
- uvc_hs_streaming_ep.wMaxPacketSize =
|
||||
- cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11));
|
||||
+ uvc_fs_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(min(opts->streaming_maxpacket, 64U));
|
||||
+ uvc_fs_streaming_ep.bInterval = 0;
|
||||
|
||||
- /* A high-bandwidth endpoint must specify a bInterval value of 1 */
|
||||
- if (max_packet_mult > 1)
|
||||
- uvc_hs_streaming_ep.bInterval = 1;
|
||||
- else
|
||||
- uvc_hs_streaming_ep.bInterval = opts->streaming_interval;
|
||||
-
|
||||
- uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size);
|
||||
- uvc_ss_streaming_ep.bInterval = opts->streaming_interval;
|
||||
- uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
|
||||
- uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
|
||||
- uvc_ss_streaming_comp.wBytesPerInterval =
|
||||
- cpu_to_le16(max_packet_size * max_packet_mult *
|
||||
- (opts->streaming_maxburst + 1));
|
||||
+ uvc_hs_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(min(opts->streaming_maxpacket, 512U));
|
||||
+ uvc_hs_streaming_ep.bInterval = 0;
|
||||
+
|
||||
+ uvc_ss_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(min(opts->streaming_maxpacket, 1024U));
|
||||
+ uvc_ss_streaming_ep.bInterval = 0;
|
||||
+ uvc_ss_streaming_comp.bmAttributes = 0;
|
||||
+ uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
|
||||
+ uvc_ss_streaming_comp.wBytesPerInterval = cpu_to_le16(0);
|
||||
+ } else {
|
||||
+ if (opts->streaming_maxpacket <= 1024) {
|
||||
+ max_packet_mult = 1;
|
||||
+ max_packet_size = opts->streaming_maxpacket;
|
||||
+ } else if (opts->streaming_maxpacket <= 2048) {
|
||||
+ max_packet_mult = 2;
|
||||
+ max_packet_size = opts->streaming_maxpacket / 2;
|
||||
+ } else {
|
||||
+ max_packet_mult = 3;
|
||||
+ max_packet_size = opts->streaming_maxpacket / 3;
|
||||
+ }
|
||||
+
|
||||
+ uvc_fs_streaming_ep.bmAttributes =
|
||||
+ USB_ENDPOINT_SYNC_ASYNC | USB_ENDPOINT_XFER_ISOC;
|
||||
+ uvc_hs_streaming_ep.bmAttributes =
|
||||
+ USB_ENDPOINT_SYNC_ASYNC | USB_ENDPOINT_XFER_ISOC;
|
||||
+ uvc_ss_streaming_ep.bmAttributes =
|
||||
+ USB_ENDPOINT_SYNC_ASYNC | USB_ENDPOINT_XFER_ISOC;
|
||||
+
|
||||
+ uvc_fs_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(min(opts->streaming_maxpacket, 1023U));
|
||||
+ uvc_fs_streaming_ep.bInterval = opts->streaming_interval;
|
||||
+
|
||||
+ uvc_hs_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(max_packet_size |
|
||||
+ ((max_packet_mult - 1) << 11));
|
||||
+
|
||||
+ /* A high-bandwidth endpoint must specify a bInterval value of 1 */
|
||||
+ if (max_packet_mult > 1)
|
||||
+ uvc_hs_streaming_ep.bInterval = 1;
|
||||
+ else
|
||||
+ uvc_hs_streaming_ep.bInterval = opts->streaming_interval;
|
||||
+
|
||||
+ uvc_ss_streaming_ep.wMaxPacketSize =
|
||||
+ cpu_to_le16(max_packet_size);
|
||||
+ uvc_ss_streaming_ep.bInterval = opts->streaming_interval;
|
||||
+ uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
|
||||
+ uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
|
||||
+ uvc_ss_streaming_comp.wBytesPerInterval =
|
||||
+ cpu_to_le16(max_packet_size * max_packet_mult *
|
||||
+ (opts->streaming_maxburst + 1));
|
||||
+ }
|
||||
|
||||
/* Allocate endpoints. */
|
||||
if (opts->enable_interrupt_ep) {
|
||||
diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h
|
||||
index 3ac392cbb779..b57e2d10ddcd 100644
|
||||
--- a/drivers/usb/gadget/function/u_uvc.h
|
||||
+++ b/drivers/usb/gadget/function/u_uvc.h
|
||||
@@ -24,6 +24,7 @@ struct f_uvc_opts {
|
||||
unsigned int streaming_interval;
|
||||
unsigned int streaming_maxpacket;
|
||||
unsigned int streaming_maxburst;
|
||||
+ unsigned int streaming_bulk;
|
||||
|
||||
unsigned int control_interface;
|
||||
unsigned int streaming_interface;
|
||||
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
|
||||
index a4a2d3dcb0d6..80817ff1b6fe 100644
|
||||
--- a/drivers/usb/gadget/function/uvc_configfs.c
|
||||
+++ b/drivers/usb/gadget/function/uvc_configfs.c
|
||||
@@ -3751,6 +3751,7 @@ UVC_ATTR(f_uvc_opts_, cname, cname)
|
||||
UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
|
||||
UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
|
||||
UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
|
||||
+UVCG_OPTS_ATTR(streaming_bulk, streaming_bulk, 1);
|
||||
|
||||
#undef UVCG_OPTS_ATTR
|
||||
|
||||
@@ -3800,6 +3801,7 @@ static struct configfs_attribute *uvc_attrs[] = {
|
||||
&f_uvc_opts_attr_streaming_interval,
|
||||
&f_uvc_opts_attr_streaming_maxpacket,
|
||||
&f_uvc_opts_attr_streaming_maxburst,
|
||||
+ &f_uvc_opts_attr_streaming_bulk,
|
||||
&f_uvc_opts_string_attr_function_name,
|
||||
NULL,
|
||||
};
|
||||
47
scripts/kernel/uvc-debug.patch
Normal file
47
scripts/kernel/uvc-debug.patch
Normal file
@ -0,0 +1,47 @@
|
||||
--- a/drivers/usb/gadget/function/uvc_video.c
|
||||
+++ b/drivers/usb/gadget/function/uvc_video.c
|
||||
@@
|
||||
int uvcg_video_enable(struct uvc_video *video)
|
||||
{
|
||||
int ret;
|
||||
|
||||
+ if (!video) {
|
||||
+ pr_err("uvcg_video_enable: missing video\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!video->uvc || !video->uvc->func.config ||
|
||||
+ !video->uvc->func.config->cdev) {
|
||||
+ pr_err("uvcg_video_enable: missing uvc/func/config video=%p uvc=%p\n",
|
||||
+ video, video->uvc);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
if (video->ep == NULL) {
|
||||
uvcg_info(&video->uvc->func,
|
||||
"Video enable failed, device is uninitialized.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
+
|
||||
+ if (!video->kworker || !video->async_wq) {
|
||||
+ uvcg_err(&video->uvc->func,
|
||||
+ "Video enable failed, missing worker(s) kworker=%p async_wq=%p\n",
|
||||
+ video->kworker, video->async_wq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!video->queue.queue.dev) {
|
||||
+ uvcg_err(&video->uvc->func,
|
||||
+ "Video enable failed, missing queue device\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ uvcg_info(&video->uvc->func,
|
||||
+ "Video enable start: video=%p ep=%p kworker=%p async_wq=%p req_size=%u max_payload=%u requests=%u reqs_per_frame=%u use_sg=%u flags=0x%x\n",
|
||||
+ video, video->ep, video->kworker, video->async_wq,
|
||||
+ video->req_size, video->max_payload_size,
|
||||
+ video->uvc_num_requests, video->reqs_per_frame,
|
||||
+ video->queue.use_sg, video->queue.flags);
|
||||
|
||||
/*
|
||||
* Safe to access request related fields without req_lock because
|
||||
Loading…
x
Reference in New Issue
Block a user