uvc: read fifo caps from debugfs

This commit is contained in:
Brad Stein 2026-01-10 13:08:38 -03:00
parent b6479acf11
commit 11c615d0b7
2 changed files with 97 additions and 15 deletions

View File

@ -131,12 +131,50 @@ uvc_fifo_min() {
END { if (min != "") print min }'
}
uvc_fifo_min_debugfs() {
local path="$1"
awk -F': ' '/^g_tx_fifo_size\\[/{print $2}' "$path" 2>/dev/null | awk '
$1 > 0 { if (min == "" || $1 < min) min = $1 }
END { if (min != "") print min }'
}
uvc_fifo_np_debugfs() {
local path="$1"
awk -F': ' '/^g_np_tx_fifo_size/{print $2; exit}' "$path" 2>/dev/null
}
compute_uvc_payload_cap() {
UVC_PAYLOAD_CAP=""
UVC_PAYLOAD_SRC=""
UVC_PAYLOAD_PCT=""
UVC_FIFO_PERIODIC="$(uvc_fifo_min /sys/module/dwc2/parameters/g_tx_fifo_size)"
UVC_FIFO_NP="$(uvc_fifo_min /sys/module/dwc2/parameters/g_np_tx_fifo_size)"
UVC_FIFO_SRC_PERIODIC=""
UVC_FIFO_SRC_NP=""
if [[ -n $UVC_FIFO_PERIODIC ]]; then
UVC_FIFO_SRC_PERIODIC="dwc2.params"
fi
if [[ -n $UVC_FIFO_NP ]]; then
UVC_FIFO_SRC_NP="dwc2.params"
fi
UVC_UDC="$(ls /sys/class/udc 2>/dev/null | head -n1 || true)"
if [[ -n $UVC_UDC ]]; then
local params="/sys/kernel/debug/usb/$UVC_UDC/params"
if [[ -r $params ]]; then
if [[ -z $UVC_FIFO_PERIODIC ]]; then
UVC_FIFO_PERIODIC="$(uvc_fifo_min_debugfs "$params")"
if [[ -n $UVC_FIFO_PERIODIC ]]; then
UVC_FIFO_SRC_PERIODIC="debugfs.params"
fi
fi
if [[ -z $UVC_FIFO_NP ]]; then
UVC_FIFO_NP="$(uvc_fifo_np_debugfs "$params")"
if [[ -n $UVC_FIFO_NP ]]; then
UVC_FIFO_SRC_NP="debugfs.params"
fi
fi
fi
fi
if [[ -n ${LESAVKA_UVC_MAXPAYLOAD_LIMIT:-} ]]; then
UVC_PAYLOAD_CAP="${LESAVKA_UVC_MAXPAYLOAD_LIMIT}"
@ -149,18 +187,18 @@ compute_uvc_payload_cap() {
if [[ -n $UVC_BULK ]]; then
if [[ -n $UVC_FIFO_NP ]]; then
chosen="$UVC_FIFO_NP"
UVC_PAYLOAD_SRC="dwc2.g_np_tx_fifo_size"
UVC_PAYLOAD_SRC="${UVC_FIFO_SRC_NP:-dwc2.g_np_tx_fifo_size}"
elif [[ -n $UVC_FIFO_PERIODIC ]]; then
chosen="$UVC_FIFO_PERIODIC"
UVC_PAYLOAD_SRC="dwc2.g_tx_fifo_size"
UVC_PAYLOAD_SRC="${UVC_FIFO_SRC_PERIODIC:-dwc2.g_tx_fifo_size}"
fi
else
if [[ -n $UVC_FIFO_PERIODIC ]]; then
chosen="$UVC_FIFO_PERIODIC"
UVC_PAYLOAD_SRC="dwc2.g_tx_fifo_size"
UVC_PAYLOAD_SRC="${UVC_FIFO_SRC_PERIODIC:-dwc2.g_tx_fifo_size}"
elif [[ -n $UVC_FIFO_NP ]]; then
chosen="$UVC_FIFO_NP"
UVC_PAYLOAD_SRC="dwc2.g_np_tx_fifo_size"
UVC_PAYLOAD_SRC="${UVC_FIFO_SRC_NP:-dwc2.g_np_tx_fifo_size}"
fi
fi
@ -181,7 +219,7 @@ compute_uvc_payload_cap() {
compute_uvc_payload_cap
if [[ -n $UVC_PAYLOAD_CAP && $UVC_PAYLOAD_CAP -gt 0 ]]; then
log "UVC fifo periodic=${UVC_FIFO_PERIODIC:-?} np=${UVC_FIFO_NP:-?} cap=${UVC_PAYLOAD_CAP}B pct=${UVC_PAYLOAD_PCT:-?} src=${UVC_PAYLOAD_SRC:-?}"
log "UVC fifo periodic=${UVC_FIFO_PERIODIC:-?} np=${UVC_FIFO_NP:-?} cap=${UVC_PAYLOAD_CAP}B pct=${UVC_PAYLOAD_PCT:-?} src=${UVC_PAYLOAD_SRC:-?} udc=${UVC_UDC:-?}"
if ((UVC_MAXPACKET > UVC_PAYLOAD_CAP)); then
log "clamping UVC maxpacket $UVC_MAXPACKET -> $UVC_PAYLOAD_CAP"
UVC_MAXPACKET=$UVC_PAYLOAD_CAP

View File

@ -807,21 +807,35 @@ fn compute_payload_cap(bulk: bool) -> Option<PayloadCap> {
});
}
let periodic_dw = read_fifo_min("/sys/module/dwc2/parameters/g_tx_fifo_size");
let non_periodic_dw = read_fifo_min("/sys/module/dwc2/parameters/g_np_tx_fifo_size");
let mut periodic = read_fifo_min("/sys/module/dwc2/parameters/g_tx_fifo_size")
.map(|v| (v, "dwc2.params"));
let mut non_periodic = read_fifo_min("/sys/module/dwc2/parameters/g_np_tx_fifo_size")
.map(|v| (v, "dwc2.params"));
if periodic.is_none() || non_periodic.is_none() {
if let Some((p, np)) = read_debugfs_fifos() {
if periodic.is_none() {
periodic = p.map(|v| (v, "debugfs.params"));
}
if non_periodic.is_none() {
non_periodic = np.map(|v| (v, "debugfs.params"));
}
}
}
let periodic_dw = periodic.map(|(v, _)| v);
let non_periodic_dw = non_periodic.map(|(v, _)| v);
let (fifo_dw, source) = if bulk {
if let Some(np) = non_periodic_dw {
(np, "dwc2.g_np_tx_fifo_size")
} else if let Some(p) = periodic_dw {
(p, "dwc2.g_tx_fifo_size")
if let Some((np, src)) = non_periodic {
(np, src)
} else if let Some((p, src)) = periodic {
(p, src)
} else {
return None;
}
} else if let Some(p) = periodic_dw {
(p, "dwc2.g_tx_fifo_size")
} else if let Some(np) = non_periodic_dw {
(np, "dwc2.g_np_tx_fifo_size")
} else if let Some((p, src)) = periodic {
(p, src)
} else if let Some((np, src)) = non_periodic {
(np, src)
} else {
return None;
};
@ -855,6 +869,36 @@ fn read_fifo_min(path: &str) -> Option<u32> {
.min()
}
fn read_debugfs_fifos() -> Option<(Option<u32>, Option<u32>)> {
let udc = std::fs::read_dir("/sys/class/udc")
.ok()?
.filter_map(|e| e.ok())
.filter_map(|e| e.file_name().into_string().ok())
.next()?;
let path = format!("/sys/kernel/debug/usb/{udc}/params");
let text = std::fs::read_to_string(path).ok()?;
let mut periodic: Option<u32> = None;
let mut non_periodic: Option<u32> = None;
for line in text.lines() {
let mut parts = line.splitn(2, ':');
let key = parts.next()?.trim();
let val = parts.next()?.trim().parse::<u32>().ok()?;
if key == "g_np_tx_fifo_size" {
non_periodic = Some(val);
} else if key.starts_with("g_tx_fifo_size[") && val > 0 {
periodic = Some(match periodic {
Some(prev) => prev.min(val),
None => val,
});
}
}
if periodic.is_none() && non_periodic.is_none() {
None
} else {
Some((periodic, non_periodic))
}
}
const IOC_NRBITS: u8 = 8;
const IOC_TYPEBITS: u8 = 8;
const IOC_SIZEBITS: u8 = 14;