diff --git a/.gitignore b/.gitignore index ae888cc..4278400 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,7 @@ __pycache__/ *~ .vscode/ .idea/ + +logs +state +quest-pro-kexec diff --git a/module/Makefile b/module/Makefile index b7ad14d..586ca53 100644 --- a/module/Makefile +++ b/module/Makefile @@ -10,6 +10,7 @@ obj-m += usb_log.o quest_kexec-y := loader.o transition.o # Without this define the module can only stage (execute=1 is refused). ccflags-y += -DQKX_ENABLE_EXPERIMENTAL_JUMP +ccflags-y += -I$(srctree)/drivers/usb/dwc3 else KDIR ?= $(error set KDIR to the built Android kernel output directory) LOCALVERSION ?= diff --git a/module/loader.c b/module/loader.c index bcd99a7..ec30c52 100644 --- a/module/loader.c +++ b/module/loader.c @@ -29,6 +29,7 @@ #include #include #include +#include "core.h" /* Matching kernel's drivers/usb/dwc3; no guessed offsets. */ #define QKX_LO 0x90000000ULL #define QKX_HI 0x93400000ULL @@ -784,11 +785,27 @@ static int __maybe_unused qkx_execute(void) } /* Stop gadget traffic and controller Run/Stop without tearing down the * Qualcomm glue power domain. Full driver unbind hard-resets the board. */ - qkx_phase(10, "suspending Android DWC3 gadget", false); - ret = suspend_dwc3_gadget(dev_get_drvdata(usb_core)); - pr_emerg("quest_kexec: DWC3 gadget suspend returned %d\n", ret); - if (ret) - panic("quest_kexec: DWC3 gadget suspend failed (%d)", ret); + { + struct dwc3 *dwc = dev_get_drvdata(usb_core); + int in_lpm = atomic_read(&dwc->in_lpm); + + pr_emerg("quest_kexec: DWC3 in_lpm=%d gadget_driver=%s\n", + in_lpm, dwc->gadget_driver ? "bound" : "none"); + /* Qualcomm defines in_lpm as controller clocks off. The stock + * gadget suspend callback starts with unguarded MMIO, which can + * hang the CPU in charger-only/no-host operation. Already-low-power + * hardware needs no further gadget stop; preserve its power domain. + */ + if (in_lpm) { + qkx_phase(10, "DWC3 already in low power; skipping gadget MMIO", false); + } else { + qkx_phase(10, "suspending Android DWC3 gadget", false); + ret = suspend_dwc3_gadget(dwc); + pr_emerg("quest_kexec: DWC3 gadget suspend returned %d\n", ret); + if (ret) + panic("quest_kexec: DWC3 gadget suspend failed (%d)", ret); + } + } put_device(usb_core); usb_core = NULL; diff --git a/tools/device/qkx_fsmap b/tools/device/qkx_fsmap index 4180963..4d2a290 100755 Binary files a/tools/device/qkx_fsmap and b/tools/device/qkx_fsmap differ diff --git a/tools/device/qkx_fsmap.c b/tools/device/qkx_fsmap.c index 40d68e2..8d85a72 100644 --- a/tools/device/qkx_fsmap.c +++ b/tools/device/qkx_fsmap.c @@ -84,6 +84,40 @@ static int do_alloc(const char *path, unsigned long long size) return 0; } +/* Extend an existing pinned file. Blocks already allocated keep their place, + * so maps of the old size stay valid; only new extents are appended. */ +static int do_grow(const char *path, unsigned long long size) +{ + struct stat st; + uint32_t pin = 1; + int fd; + + fd = open(path, O_RDWR); + if (fd < 0) + return die("open"); + if (fstat(fd, &st)) + return die("fstat"); + if (size <= (unsigned long long)st.st_size) { + fprintf(stderr, "qkx_fsmap: %s is already %llu bytes\n", path, + (unsigned long long)st.st_size); + return 1; + } + if (ioctl(fd, F2FS_IOC_SET_PIN_FILE, &pin)) + return die("F2FS_IOC_SET_PIN_FILE"); + if (fallocate(fd, 0, 0, (off_t)size)) + return die("fallocate"); + if (fsync(fd)) + return die("fsync"); + pin = 0; + if (!ioctl(fd, F2FS_IOC_GET_PIN_FILE, &pin) && pin) { + fprintf(stderr, "qkx_fsmap: %s reports %u pin/GC failures\n", + path, pin); + return 1; + } + close(fd); + return 0; +} + static int do_map(const char *path, unsigned long long unit) { char buf[sizeof(struct fiemap) + MAX_EXTENTS * sizeof(struct fiemap_extent)]; @@ -159,6 +193,8 @@ int main(int argc, char **argv) { if (argc == 4 && !strcmp(argv[1], "alloc")) return do_alloc(argv[2], strtoull(argv[3], NULL, 0)); + if (argc == 4 && !strcmp(argv[1], "grow")) + return do_grow(argv[2], strtoull(argv[3], NULL, 0)); if (argc == 3 && !strcmp(argv[1], "map")) return do_map(argv[2], 1); if (argc == 4 && !strcmp(argv[1], "mapdd")) { @@ -172,6 +208,7 @@ int main(int argc, char **argv) } fprintf(stderr, "usage: qkx_fsmap alloc \n" + " qkx_fsmap grow \n" " qkx_fsmap map \n" " qkx_fsmap mapdd \n"); return 1;