环境目标板：QRB5165 EB5基线：qrb5165-eb5.dts 继承 qrb5165-rb5.dts目标：恢复 pcie1 下有线网卡 endpoint 枚举主线 dts// SPDX-License-Identifier: BSD-3-Clause /* * Qualcomm Robotics EB5 platform based on QRB5165/RB5 */ /dts-v1/; #include "qrb5165-rb5.dts" / { model = "Qualcomm Technologies, Inc. qrb5165 IOT EB5"; compatible = "qcom,kona-iot", "qcom,kona", "qcom,iot", "qcom,eb5", "qcom,qrb5165-rb5", "qcom,sm8250"; aliases { ufshc1 = &ufs_mem_hc; pci-domain0 = &pcie0; pci-domain1 = &pcie1; pci-domain2 = &pcie2; }; }; &pcie1 { status = "okay"; max-link-speed = <3>; num-lanes = <2>; wake-gpios = <&tlmm 84 GPIO_ACTIVE_HIGH>; vdda-supply = <&vreg_l9a_1p2>; vddpe-3v3-supply = <&vreg_l11c_3p3>; /* * Remove iommu-map so qcom_pcie_config_sid_1_9_0() returns early * and never clears BDF_TO_SID_BYPASS. With bypass ON (hardware * default), inbound PCIe completions skip SMMU BDF-to-SID lookup. * * Background: during PCI bus walk the SMMU has no context banks for * downstream-device SIDs yet (iommu_attach_device() is called only * after device_add(), i.e. AFTER the first config read). The vendor * msm_pcie driver never touches BDF_TO_SID_CFG, so bypass stays ON * there and ASM2806 completions flow through unblocked. */ /delete-property/ iommu-map; /* * Append the helper as an extra clock entry so fw_devlink ensures * the helper probes (and gpio141 is driven) before qcom-pcie probes. * qcom-pcie only requests clocks by the names it knows; "lan-en" is * silently ignored by the driver but honored by fw_devlink. */ clocks = <&gcc GCC_PCIE_1_PIPE_CLK>, <&gcc GCC_PCIE_1_AUX_CLK>, <&gcc GCC_PCIE_1_CFG_AHB_CLK>, <&gcc GCC_PCIE_1_MSTR_AXI_CLK>, <&gcc GCC_PCIE_1_SLV_AXI_CLK>, <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>, <&gcc GCC_PCIE_WIGIG_CLKREF_EN>, <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>, <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>, <&eb5_pcie1_helper>; clock-names = "pipe", "aux", "cfg", "bus_master", "bus_slave", "slave_q2a", "ref", "tbu", "ddrss_sf_tbu", "lan-en"; pinctrl-0 = <&pcie1_default_state>; pcie@0 { }; }; /* * Lightweight anchor node for the out-of-tree eb5-pcie1-helper kmod. * The driver waits for RC1 link stabilisation and then rescans pcie1 (domain 1) * so the ASM2806 cascade + RTL8168 endpoints can be discovered without any * modifications to qcom.c. */ / { eb5_pcie1_helper: eb5-pcie1-helper { compatible = "qcom,eb5-pcie1-helper"; lan-en-gpios = <&tlmm 141 GPIO_ACTIVE_HIGH>; #clock-cells = <0>; status = "okay"; }; }; &pcie2 { status = "disabled"; }; &pcie2_phy { status = "disabled"; }; &tlmm { };EB5 Helper Module// SPDX-License-Identifier: GPL-2.0 /* * pcie-qcom-eb5-helper.c - PCIe1 ASM2806 bridge bring-up helper for QRB5165 EB5 * * The Qualcomm vendor 4.19 kernel has a private "use-pcie-bridge-asm2806" DT * property that drives gpio141 (ASM2806 bridge-enable) before the RC1 PCIe * controller enumerates the bus. Mainline qcom-pcie has no such logic. * * This driver: * 1. Acquires gpio141 and drives it HIGH on probe (before qcom-pcie touches * PERST#). * 2. Registers itself as a dummy fixed-rate clock provider (#clock-cells = <0>), * which qrb5165-eb5.dts adds to pcie1's clock list. fw_devlink sees this * phandle and guarantees that pcie1 will NOT be probed until this driver's * probe() returns successfully. * 3. Schedules a deferred rescan after the ASM2806 cascade downstream links * finish training. The rescan explicitly programs bridge MEMORY_BASE/LIMIT * registers to hardware — pci_assign_unassigned_bus_resources() only updates * kernel data structures but does NOT write the bridge window registers, * which would leave the RTL8168 endpoints inaccessible. * * Result: gpio141 is driven high BEFORE qcom_pcie_host_init() de-asserts PERST#, * so the ASM2806 bridge is powered and ready for config-space enumeration. * * Nothing in qcom.c / pcie-qcom.c is modified. */ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/clk-provider.h> #include <linux/clk.h> #include <linux/pci.h> #include <linux/workqueue.h> #include <linux/io.h> /* PCI domain 1, root bus 0 — matches pcie1 (1c08000.pcie) */ #define EB5_PCIE1_DOMAIN 1 #define EB5_PCIE1_ROOT_BUS 0 /* * Poll interval while waiting for pcie1 to create its root bus. * pcie1 probe can take 10-15 s at boot; we retry up to 30 times (30 s). */ #define EB5_POLL_INTERVAL_MS 1000 #define EB5_POLL_MAX_RETRIES 30 #define DRV_NAME "qcom-eb5-pcie1-helper" struct eb5_pcie_helper { struct gpio_desc *lan_en_gpio; struct clk_hw clk_hw; struct delayed_work rescan_work; }; static const struct clk_ops eb5_lan_clk_ops = { /* no-op clock, ordering only */ }; /* * program_bridge_windows - write bridge memory windows to hardware registers. * * pci_assign_unassigned_bus_resources() assigns memory windows in the kernel's * resource tree but does NOT write PCI_MEMORY_BASE / PCI_MEMORY_LIMIT to the * bridge's config space. Without this step the bridge does not forward memory * transactions downstream, so endpoint drivers fail on their very first MMIO * access. Recurse into child buses so all levels of ASM2806 are programmed. */ static void program_bridge_windows(struct pci_bus *bus) { struct pci_dev *dev; list_for_each_entry(dev, &bus->devices, bus_list) { struct resource *res; u16 cmd; if (!dev->subordinate) continue; /* Write 32-bit non-prefetchable memory window */ res = &dev->resource[PCI_BRIDGE_MEM_WINDOW]; if (resource_size(res) > 0) { u16 mem_base = (res->start >> 16) & 0xfff0; u16 mem_limit = (res->end >> 16) & 0xfff0; pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); dev_info(&dev->dev, "bridge mem window programmed: %pR\n", res); } /* Write I/O window if present */ res = &dev->resource[PCI_BRIDGE_IO_WINDOW]; if (resource_size(res) > 0) { pci_write_config_byte(dev, PCI_IO_BASE, (res->start >> 8) & 0xf0); pci_write_config_byte(dev, PCI_IO_LIMIT, (res->end >> 8) & 0xf0); } /* Enable bus-mastering and memory-space decoding on the bridge */ pci_read_config_word(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, cmd); program_bridge_windows(dev->subordinate); } } static void eb5_pcie1_rescan_work(struct work_struct *work) { struct eb5_pcie_helper *h = container_of(work, struct eb5_pcie_helper, rescan_work.work); struct pci_bus *root_bus; int retries = 0; /* Re-assert gpio141 in case it was reset during suspend/resume */ gpiod_set_value_cansleep(h->lan_en_gpio, 1); /* * pcie1 probe (and bus creation) can take 10-15 s at boot — much * longer than the helper's own probe. Poll until the root bus * appears, then give the ASM2806 downstream links an extra second * to finish training before we scan. */ while (retries < EB5_POLL_MAX_RETRIES) { root_bus = pci_find_bus(EB5_PCIE1_DOMAIN, EB5_PCIE1_ROOT_BUS); if (root_bus) break; pr_debug(DRV_NAME ": waiting for pcie1 bus (attempt %d/%d)\n", retries + 1, EB5_POLL_MAX_RETRIES); msleep(EB5_POLL_INTERVAL_MS); retries++; } if (!root_bus) { pr_err(DRV_NAME ": domain %u bus %02x not found after %d s, giving up\n", EB5_PCIE1_DOMAIN, EB5_PCIE1_ROOT_BUS, EB5_POLL_MAX_RETRIES); return; } /* Extra settling time for ASM2806 downstream link training */ msleep(1000); pr_info(DRV_NAME ": rescanning pcie1 (domain %u bus %02x) after %d poll(s)\n", EB5_PCIE1_DOMAIN, EB5_PCIE1_ROOT_BUS, retries); /* * Issue a Secondary Bus Reset (SBR) via the root port's Bridge Control * register. This pulses the downstream PERST# from the RC side without * needing direct GPIO access. The ASM2806 may have been unresponsive * during the initial enumeration because its internal init was not yet * complete when qcom-pcie first de-asserted PERST# at probe time. * Driving SBR here — after gpio141 has been high for several seconds — * gives the ASM2806 a clean reset cycle with power already stable. */ { struct pci_dev *rp = pci_get_domain_bus_and_slot( EB5_PCIE1_DOMAIN, 0, PCI_DEVFN(0, 0)); if (rp) { u16 bctl; pci_read_config_word(rp, PCI_BRIDGE_CONTROL, &bctl); /* Assert Secondary Bus Reset */ pci_write_config_word(rp, PCI_BRIDGE_CONTROL, bctl | PCI_BRIDGE_CTL_BUS_RESET); msleep(100); /* hold reset ≥ 100 ms (PCIe r3.0 §6.6.1) */ /* De-assert Secondary Bus Reset */ pci_write_config_word(rp, PCI_BRIDGE_CONTROL, bctl); msleep(500); /* wait for ASM2806 to finish link re-training */ dev_info(&rp->dev, DRV_NAME ": SBR pulse done, waiting for ASM2806\n"); pci_dev_put(rp); } else { pr_warn(DRV_NAME ": root port not found, skipping SBR\n"); } } pci_lock_rescan_remove(); /* Step 1: discover new devices (ASM2806 cascade + RTL8168) */ pci_scan_child_bus(root_bus); /* Step 2: assign BARs and bridge windows in kernel resource structs */ pci_assign_unassigned_bus_resources(root_bus); /* * Step 3: write bridge MEMORY_BASE/LIMIT to hardware config space. * This is the step that pci_rescan_bus() / pci_assign_…() omit, * and without it the RTL8168 endpoints are unreachable via MMIO. */ program_bridge_windows(root_bus); /* Step 4: add devices to driver model — triggers driver probes */ pci_bus_add_devices(root_bus); pci_unlock_rescan_remove(); pr_info(DRV_NAME ": rescan complete, bridges programmed\n"); } /* Forward declaration for sysfs attribute */ static DEVICE_ATTR_WO(reset_asm2806); static int eb5_pcie_helper_probe(struct platform_device *pwd) { struct device *dev = &pwd->dev; struct eb5_pcie_helper *h; struct clk_init_data init = {}; int ret; h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); if (!h) return -ENOMEM; /* * Acquire gpio141 (ASM2806 bridge-enable) and drive it HIGH. * This must happen before qcom-pcie de-asserts PERST# on RC1. * The clock provider registration below ensures that qcom-pcie * does not even begin probing until after this point. */ h->lan_en_gpio = devm_gpiod_get(dev, "lan-en", GPIOD_OUT_HIGH); if (IS_ERR(h->lan_en_gpio)) return dev_err_probe(dev, PTR_ERR(h->lan_en_gpio), "failed to get lan-en gpio\n"); msleep(50); /* allow ASM2806 to become ready */ dev_info(dev, "lan-en (gpio141) asserted high\n"); /* * Register a zero-rate fixed clock so that fw_devlink can enforce * the probe ordering: pcie1 (which lists us in its 'clocks') will * not probe before of_clk_add_hw_provider() returns. */ init.name = DRV_NAME; init.ops = &eb5_lan_clk_ops; h->clk_hw.init = &init; ret = devm_clk_hw_register(dev, &h->clk_hw); if (ret) return dev_err_probe(dev, ret, "clk_hw_register failed\n"); ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &h->clk_hw); if (ret) return dev_err_probe(dev, ret, "of_clk_add_hw_provider failed\n"); /* Start polling immediately; the work itself waits for the bus */ INIT_DELAYED_WORK(&h->rescan_work, eb5_pcie1_rescan_work); schedule_delayed_work(&h->rescan_work, 0); platform_set_drvdata(pwd, h); ret = device_create_file(dev, &dev_attr_reset_asm2806.attr); if (ret) dev_warn(dev, "failed to create reset_asm2806 sysfs: %d\n", ret); dev_info(dev, "clock provider registered, waiting for pcie1 bus\n"); return 0; } static void eb5_pcie_helper_remove(struct platform_device *pdev) { struct eb5_pcie_helper *h = platform_get_drvdata(pdev); cancel_delayed_work_sync(&h->rescan_work); device_remove_file(&pwd->dev, &dev_attr_reset_asm2806.attr); } static const struct of_device_id eb5_pcie_helper_of_match[] = { { .compatible = "qcom,eb5-pcie1-helper" }, {} }; MODULE_DEVICE_TABLE(of, eb5_pcie_helper_of_match); static struct platform_driver eb5_pcie_helper_driver = { .probe = eb5_pcie_helper_probe, .remove = eb5_pcie_helper_remove, .driver = { .name = DRV_NAME, .of_match_table = eb5_pcie_helper_of_match, }, }; builtin_platform_driver(eb5_pcie_helper_driver); /* Sysfs interface to trigger full reset sequence */ static ssize_t reset_asm2806_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct eb5_pcie_helper *h = dev_get_drvdata(dev); void __iomem *parf; struct pci_bus *root_bus; dev_info(dev, "triggering full ASM2806 reset sequence...\n"); /* 1. Power cycle gpio141 */ gpiod_set_value_cansleep(h->lan_en_gpio, 0); msleep(200); gpiod_set_value_cansleep(h->lan_en_gpio, 1); msleep(500); /* 2. Write bypass bit */ parf = ioremap(0x1c0ac00, 4); if (parf) { writel(BIT(0), parf); dev_info(dev, "BDF_TO_SID_BYPASS set\n"); iounmap(parf); } /* 3. Trigger SBR */ root_bus = pci_find_bus(EB5_PCIE1_DOMAIN, EB5_PCIE1_ROOT_BUS); if (root_bus) { struct pci_dev *rp = pci_get_domain_bus_and_slot( EB5_PCIE1_DOMAIN, 0, PCI_DEVFN(0, 0)); if (rp) { u16 bctl; pci_read_config_word(rp, PCI_BRIDGE_CONTROL, &bctl); pci_write_config_word(rp, PCI_BRIDGE_CONTROL, bctl | PCI_BRIDGE_CTL_BUS_RESET); msleep(100); pci_write_config_word(rp, PCI_BRIDGE_CONTROL, bctl); msleep(500); pci_dev_put(rp); dev_info(dev, "SBR done\n"); } } /* 4. Rescan */ pci_lock_rescan_remove(); pci_scan_child_bus(root_bus); pci_bus_add_devices(root_bus); pci_unlock_rescan_remove(); dev_info(dev, "reset sequence complete\n"); return count; }已执行测试（按大类）1) DTS 基线与 include 链确认确认 qrb5165-eb5.dts -> qrb5165-rb5.dts -> sm8250.dtsi 链路正确。校对 pcie1 主线默认脚位语义：perst=82、wake=84。2) pcie1 链路参数测试&pcie1 设置：max-link-speed = <1>（降速到 Gen1）。&pcie1 设置：num-lanes = <1>（单 lane 试验）。结果：0001 域仍仅有 root port，无桥后 endpoint。3) IOMMU 映射扩展测试将 iommu-map 从基础项扩展到多 BDF（覆盖 0x0..0x600 相关条目）。结果：未触发有线 endpoint 出现。4) 供电影响排查增加/确认 vdda-supply 与 vddpe-3v3-supply。结果：无显著变化，pcie1 仍空下游。5) WAKE/RESET 脚位组合测试wake-gpios 做过候选切换（22/84），最终回归 84（与主线/旧树一致）。pcie@0/reset-gpios 做过极性 A/B 试验（active low/high 组合对比）。结果：仍未枚举到有线 endpoint。6) 141 板级控制线测试早期方案：gpio141 作为 gpio-hog output-high（常高驱动）。最新方案：移除 hog，改为 pcie1 附加 pinctrl（pcie1_lan1_wake_default，bias-pull-up 输入态），贴近旧树语义。结果：等待该版本实机回传确认。7) pcie2 冲突隔离测试&pcie2、&pcie2_phy 设为 disabled。结果：未改变 pcie1 无下游端点现象。8) GPIO 共享告警处置观察到告警：gpio_shared_add_proxy_lookup / qcom_pcie_probe。做过修复：删除 &pcie1 的 perst-gpios，保留 pcie@0/reset-gpios，避免同线重复申请。新日志定位：告警主要落在 1c00000.pcie (pcie0)，非 1c08000.pcie (pcie1)。9) 旧内核基线确认（4.19）在旧内核 4.19.125-perf-v2 下，0001 域可完整枚举：0001:01:00.0/0001:02:00.0/0001:02:06.0/0001:02:0e.0 均为 ASMedia 1b21:28060001:04:00.0 与 0001:05:00.0 为 RTL8111/8168 (10ec:8168)旧日志明确出现 RC1: asm2806(1)，说明厂商侧存在 RC1 私有桥控制语义。10) 主线运行时补偿脚本尝试（失败）在主线 6.19.0-dirty 运行 pcie1-kick.sh：gpioset gpiochip0 141=... 返回 Invalid argument/sys/bus/platform/drivers/qcom-pcie/{bind,unbind} 不存在或不可用，无法运行时重绑 RC1结论：该平台当前不支持“运行时重绑+踢脚”路径，需回到“重启生效”的 DTS 单变量法。11) 纯 DTS 单变量回归（最新）已将 gpio141 改回 gpio-hog output-high，并移除 pcie1 的 pcie1_lan1_wake_default 引用。该版本仅改 gpio141 启动策略，便于与上一版直接对比。12) 纯 DTS 单变量（本轮）将 gpio141 从 gpio-hog 改为 pcie1 设备级 pinctrl（pcie1_lan1_en_default），配置为 output-high。&pcie1 的 pinctrl-0 调整为 <&pcie1_default_state>, <&pcie1_lan1_en_default>。保持 wake-gpios=84、reset-gpios=82、qcom.c 不变，确保本轮仅变更 141 的所有权与生效时机。结果：等待该版本实机回传确认。当前观测结论（最新）主线 6.19 lspci 稳定仅有 0001:00:00.0（root port），ASM2806 / RTL8168 不可见vendor 4.19 完整枚举：ASM2806 × 4 + RTL8168 × 2，eth1 UP链路速度不是根因：Gen1 x1 下 config TLP 依然可以工作，vendor 4.19 跑 Gen3 x2 但根因另在已确认根因：主线 iommu-map 触发 BDF_TO_SID_BYPASS 被清除 → SMMU fault → 0xFFFF（见下方根因分析节）当前最新镜像（step 22）已将 iommu-map 删除，待实机验证13) built-in helper driver + gpiod 主动驱动 gpio141（本轮）背景：步骤 12 中 rescan 已成功执行（dmesg 显示 "PCI 1:00 rescan complete"），但 ASM2806 config space 返回全 0xFF，说明 gpio141 未被物理驱动。Qualcomm TLMM 的 pinctrl output-high 仅设置 mux，开机后不保证实际电平被 GPIO 控制器持续驱动。变更内容（单变量）：DTS — eb5-pcie1-helper 节点加入 lan-en-gpios = <&tlmm 141 GPIO_ACTIVE_HIGH>DTS — 从 &pcie1 pinctrl-0 移除 pcie1_lan1_en_default；从 &tlmm 删除该 pinctrl block（gpio141 所有权唯一归 helper driver）驱动 — pcie-qcom-eb5-helper.c：struct 加 struct gpio_desc *lan_en_gpio驱动 — probe 时 devm_gpiod_get_optional(dev, "lan-en", GPIOD_OUT_HIGH) 请求并立即驱动 gpio141 为高驱动 — worker 在 pci_find_bus() 前再次 gpiod_set_value_cansleep(h->lan_en_gpio, 1) + msleep(50) 确保 ASM2806 就绪预期验证口径（刷机后）：dmesg | grep -E 'eb5-pcie1|lan-en|gpio141|rescan|0001:' lspci -nn | grep '^0001:' ip -br a若仍无响应，追加：lspci -vv -s 0001:00:00.0 | grep -E 'LnkSta|Speed|Width'14) genpd provider 方案 — 让 pcie1 依赖 helper（本轮）方案来源：建议写个像 power-domain 的驱动。原理：将 helper 改为 generic_pm_domain (genpd) provider。&pcie1 的 power-domains 列表加入 <&eb5_pcie1_helper>，内核 PM domain 框架会在 qcom-pcie probe 之前自动调用 helper 的 power_on 回调，保证 gpio141 在 RC1 第一次枚举时已经 asserted。彻底不需要 rescan、delayed_work 和时序猜测。变更内容（单变量）：驱动重构 — 删除所有 pci.h / workqueue.h / delayed_work / pci_scan_child_bus 代码新结构体：struct eb5_lan_pd { struct generic_pm_domain genpd; struct gpio_desc *lan_en_gpio; }probe：devm_gpiod_get(GPIOD_OUT_HIGH) + msleep(50) + pm_genpd_init(is_off=false) + of_genpd_add_provider_simple()remove：of_genpd_del_provider() + pm_genpd_remove()power_on 回调：gpiod_set_value_cansleep(1) + msleep(50)（供 suspend/resume 使用）GENPD_FLAG_ALWAYS_ON：运行时不切断电源DTS — helper 节点加 #power-domain-cells = <0>; 并加 label eb5_pcie1_helper:DTS — &pcie1 覆盖 power-domains = <&gcc PCIE_1_GDSC>, <&eb5_pcie1_helper>; 及 power-domain-names = "gdsc", "lan-en";时序保证：fw_devlink 使 pcie1 不会在 helper 注册 genpd provider 之前 probegenpd 框架在 pcie1 上电时调用 power_on，gpio141 在 qcom_pcie_probe→link_up→enumeration 全链路之前已高预期验证口径（刷机后）：dmesg | grep -E 'eb5-pcie1|lan-en|pcie1.*power|0001:' lspci -nn | grep '^0001:' ip -br a15) 时钟 provider 排序方案（本轮）根因分析（步骤 14 失败原因）：步骤 14 添加 power-domains = <&gcc PCIE_1_GDSC>, <&eb5_pcie1_helper> 后，fw_devlink 和 genpd 两套机制各自为 pcie1↔helper 创建了一条 device_link。双 device_link 冲突导致 pci_register_host_bridge → request_resource 返回 -16 (EBUSY)，pcie1 probe 失败。当前方案（朋友思路的正确实现）：不触碰 power-domains，改用 clock provider 做排序锚点：helper 注册一个 zero-rate dummy 时钟（#clock-cells = <0>）qrb5165-eb5.dts 在 pcie1 的 clocks/clock-names 末尾加 <&eb5_pcie1_helper> "lan-en"fw_devlink 识别 clocks phandle，自动保证 pcie1 probe 在 helper probe 完成之后helper probe 时驱动 gpio141 high + msleep(50) → of_clk_add_hw_provider 完成qcom-pcie 只 devm_clk_bulk_get 它知道的 9 个名字，"lan-en" 被忽略，无副作用时序：T=1.2s: helper probe → gpio141 HIGH + clock provider 注册 → fw_devlink 放行 pcie1T=6.4s: pcie1 probe → qcom_pcie_host_init → PERST# de-assert（gpio141 已 high ≥ 5s）变更内容：驱动重构 — 移除所有 genpd/pm_domain 代码；改用 clk_init_data + devm_clk_hw_register + devm_of_clk_add_hw_providerDTS — helper 节点 #power-domain-cells → #clock-cells = <0>DTS — pcie1 恢复原始 power-domains（不再覆盖），添加完整 clocks/clock-names 列表并追加 <&eb5_pcie1_helper> "lan-en"预期 dmesg 口径：dmesg | grep -E 'eb5-pcie1|lan-en|1c08000.pcie|0001:' lspci -nn | grep '^0001:' ip -br a应看到：eb5-pcie1-helper: lan-en (gpio141) asserted high @ ~1.2seb5-pcie1-helper: clock provider registered... @ ~1.2sqcom-pcie 1c08000.pcie: PCI host bridge to bus 0001:00 @ ~6.x s（probe 不再 EBUSY）0001:01:00.0 ... 1b21:2806（ASM2806）+ 0001:04:00.0 10ec:8168（RTL8168）21) 修正为 Gen3 x2，重建镜像变更（单变量）：qrb5165-eb5.dts 中 &pcie1 的 max-link-speed = <1> → <3>，num-lanes = <1> → <2>其余不变（clock provider、gpio141、SBR 等保留）实测结果（已刷机）：LnkSta 仍为 0x1011（Gen1 x1），即使写了 max-link-speed=3 也无法训练到 Gen3手动写 LnkCtl2 TLS=Gen3（setpci ... CAP_EXP+0x30.w=0x0003）再触发 retrain → 仍 Gen1 x1PHY 寄存器层面 sm8250_qmp_gen3x2_pciephy_cfg 在主线确实存在（lanes=2，tbls_rc Gen3x2 表完整），但实际无法跑到 Gen3ASM2806 config space 仍返回 0xffffffff ❌结论：Gen1 x1 ≠ 根因。速度与 config TLP 可见性正交，Gen1 链路也应能读 config space关键反转：步骤 21 之前的假设（"Gen1 导致 ASM2806 不可见"）已被证伪。继续在旧内核 4.19 上用 pci-msm debugfs 深挖寄存器差异。22) 修复：/delete-property/ iommu-map（当前待验证）变更（单变量，仅改 DTS）：qrb5165-eb5.dts 的 &pcie1 中，将多条 iommu-map 条目替换为 /delete-property/ iommu-map;这使 qcom_pcie_config_sid_1_9_0() 因 size=0 提前返回，不清除 BDF_TO_SID_BYPASS bit其余不变（max-link-speed=3, num-lanes=2, clock provider, gpio141 均保留）镜像哈希：53d1472f5be3b1d28131ff79752dce537176661193bf33100089ea4e1bcd6066验证口径（刷机后）：dmesg | grep -E '0001:|1c08000|eb5-pcie1' lspci -nn | grep '^0001:' # 期望：1b21:2806 + 10ec:8168 ip -br a # 期望：eth0/eth1 UP # 若 ASM2806 出现但 eth DOWN，追查： dmesg | grep -E 'smmu.*fault|iommu.*error|r8169|rtl8168'预期原理：bypass=1 → SMMU 透传所有 PCIe CplD → ASM2806 config read 正常返回 0x1b212806旧内核（4.19）pci-msm debugfs 深度探查22-vendor) 确认旧内核链路和设备状态板上执行（vendor 4.19）：ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 bond0 DOWN dummy0 UNKNOWN fe80::d3f:ae5d:b7ab:4c76/64 eth1 UP 192.168.1.185/24 ... ← NIC working ✅ tailscale0 UNKNOWN 100.64.0.70/32 ... wlan0 UP 192.168.6.1/24 ... lspci -nn | grep '^0001:' 0001:00:00.0 PCI bridge [0604]: Qualcomm Device [17cb:010b] 0001:01:00.0 PCI bridge [0604]: ASMedia Technology Inc. Device [1b21:2806] (rev 01) ✅ 0001:02:00.0 PCI bridge [0604]: ASMedia Technology Inc. Device [1b21:2806] (rev 01) ✅ 0001:02:06.0 PCI bridge [0604]: ASMedia Technology Inc. Device [1b21:2806] (rev 01) ✅ 0001:02:0e.0 PCI bridge [0604]: ASMedia Technology Inc. Device [1b21:2806] (rev 01) ✅ 0001:04:00.0 Ethernet controller [0200]: Realtek ... RTL8111/8168 [10ec:8168] (rev 15) ✅ 0001:05:00.0 Ethernet controller [0200]: Realtek ... RTL8111/8168 [10ec:8168] (rev 15) ✅23-vendor) pci-msm debugfs case 9-32 探查结果执行（vendor 4.19，rc_sel=2）：echo 2 > /sys/kernel/debug/pci-msm/rc_sel for i in 9 10 11 12 13 14 15 16 20 21 22 32; do echo "=== case $i ==="; echo $i > case; dmesg | tail -5; sleep 0.3 done结果摘要：case含义输出关键内容9disable L1ssPCIe: RC1: disable L1ss10enable L1ssPCIe: RC1: enable L1ss11enumerate RC1PCIe: RC1 is already enumerated（不重枚举）12read PARF registerbase: parf: 0xffffff80089d8000，wr_offset: 0x2c0，value: 0x013write PARF register写 parf+0x2c0 = 0x0（vendor 的 wr_offset=0x2c0 对应 PARF 内一个不同寄存器，非主线 PARF_BDF_TO_SID_CFG=0x2c00）14write PARF register同 case 13（延续 wr_offset/mask/value 设置）15map LBAR 4K DDR映射 DDR + LBAR=0x40008000 到内核虚地址 0xffffff8010e4d00016unmap LBAR释放 case 15 的映射20Read DDR valuesDDR is not mapped（需先做 case 15）21Read LBAR valuesLBAR address is not mapped（需先做 case 15）22Write 0x1 to DDRDDR address is not mapped32set target speed Gen3PCIe: RC1: set target speed to Gen 3重点：case=12 读 parf+0x2c0 值为 0x0 → vendor 4.19 该偏移为零，不对应主线的 PARF_BDF_TO_SID_CFG（主线定义为 0x2c00，差了一个零）case=15 LBAR=0x40008000（vendor driver 的 debug ioremap 窗口，非 mainline ATU 0x40001000）gpio debugfs 无输出：cat /sys/kernel/debug/gpio | grep -E ' 82 | 141 ' → 空，说明 vendor 4.19 gpio 82/141 未以 debugfs 方式暴露（可能走的是 msm_pcie 私有接口）24-vendor) pci-msm case=4 shadow dump 解析执行（之前已获取）：echo 2 > /sys/kernel/debug/pci-msm/rc_sel echo 4 > /sys/kernel/debug/pci-msm/case输出（RTL8168 at 05:00.0 的 shadow registers）：shadow_dw[4]:cfg 0x10: 0x40202001 # BAR0 low (64-bit prefetchable, addr=0x40202000) shadow_dw[6]:cfg 0x18: 0x40404004 # Type-1 bridge bus numbers shadow_dw[8]:cfg 0x20: 0x40400004 # Memory Base/Limit shadow_dw[20]:cfg 0x50: 0x817005 # PCIe capability shadow_dw[30]:cfg 0x78: 0x10501f # Link cap: Gen3 x2 shadow_dw[32]:cfg 0x80: 0x10110002 # LnkSta2/LnkCtl2 shadow_dw[44]:cfg 0xb0: 0x30011 # L1 sub-state cap→ vendor RTL8168 BAR 被正确分配在 0x40202000，内存窗口 0x40400000 区域正常。根因分析（最终结论）代码路径溯源主线 ops_1_9_0（pcie-qcom.c）对应 qcom,pcie-sm8250，其 .config_sid = qcom_pcie_config_sid_1_9_0该函数逻辑：of_get_property(dev->of_node, "iommu-map", &size); if (!size) return 0; // ← 有 iommu-map 才往下走 val = readl(pcie->parf + PARF_BDF_TO_SID_CFG); // PARF_BDF_TO_SID_CFG = 0x2c00 val &= ~BDF_TO_SID_BYPASS; // ← 清除 bypass bit（BIT(0)） writel(val, pcie->parf + PARF_BDF_TO_SID_CFG); // 然后填充 BDF-to-SID 哈希表...eb5.dts 中 &pcie1 有多条 iommu-map（BDF 0x0000→0x0600），导致 config_sid 被调用bypass bit（BIT(0)）被清除 → SMMU 对所有下游设备的 CplD 执行 BDF→SID 查表PCI 枚举阶段，iommu_attach_device() 尚未被调用（它发生在 device_add() 之后，即第一次 config read 成功之后）SMMU 查 SID 0x1c81（ASM2806，BDF=0x0100）→ 无 context bank → fault → Cpl 被丢弃 → CPU 读到 0xffffffffvendor 4.19 为何正常：out-of-tree msm_pcie 驱动从不调用任何等价 config_sid 逻辑BDF_TO_SID_BYPASS（硬件上电默认值 = 1，即 bypass 开启）始终保持所有 PCIe completions 绕过 SMMU SID 查表，直达 CPU → ASM2806 config read 正常返回对比表：项目vendor 4.19 (msm_pcie)主线 6.19 (pcie-qcom.c)驱动out-of-tree，特有 RC 初始化主线，通用 DWC ops_1_9_0config_sid 调用从不调用iommu-map 非空时调用BDF_TO_SID_BYPASS= 1（硬件默认，从未清除）= 0（被主动清除）ASM2806 CplD 路径绕过 SMMU → CPU ✅SMMU fault → 丢包 ❌LnkStaGen3 x2Gen1 x1（PHY 实际不支持 Gen3）
前置准备Certimate ：已安装并配置好，能够成功申请/续期证书。aaPanel ：面板已安装并正在运行。已在面板中创建了需要部署证书的 网站 。Python 3 环境（aaPanel 通常自带 Python 3）。第一步：配置 aaPanel API为了让脚本能够通过接口操作面板，需要在宝塔面板中开启 API 功能。登录 aaPanel/宝塔面板。点击左侧菜单的 面板设置 (Settings) 。找到 API 接口 (API Interface) 选项，点击开启。记录关键信息 ：接口密钥 (API Secret Key) ：复制并保存，稍后会用到。面板地址 (Panel URL) ：通常是 http://IP:端口。配置 IP 白名单 ：在 API 设置中的“IP 白名单”栏，填入部署 Certimate 的服务器 IP 地址。第二步：准备部署脚本我们将使用一个 Python 脚本来完成“上传证书”和“部署到站点”两个动作。该脚本会自动处理宝塔 API 需要的签名验证。脚本文件在 Certimate 的部署目标服务器上（或 Certimate 容器内），创建一个文件，例如 deploy_aapanel.py，并将以下代码粘贴进去：#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import os import ssl import sys import time import hashlib import urllib.parse import urllib.request import urllib.error # --- 工具函数 --- def is_true(value: str | None) -> bool: if value is None: return False return value.strip().lower() in {"1", "true", "yes", "y", "on"} DEBUG = is_true(os.getenv("DEBUG")) def debug(msg: str) -> None: if DEBUG: print(f"[DEBUG] {msg}", file=sys.stderr) def require_env(name: str) -> str: value = os.getenv(name) if not value: print(f"❌ 错误: 环境变量 [{name}] 未设置。", file=sys.stderr) raise SystemExit(1) return value def md5_hex(text: str) -> str: return hashlib.md5(text.encode("utf-8")).hexdigest() def add_auth_query(url: str, api_secret_key: str) -> tuple[str, int, str]: # 生成宝塔 API 认证所需的 request_token now = int(time.time() * 1000) request_token = md5_hex(str(now) + md5_hex(api_secret_key)) parts = urllib.parse.urlsplit(url) existing = urllib.parse.parse_qsl(parts.query, keep_blank_values=True) existing.extend([("request_time", str(now)), ("request_token", request_token)]) new_query = urllib.parse.urlencode(existing) return urllib.parse.urlunsplit((parts.scheme, parts.netloc, parts.path, new_query, parts.fragment)), now, request_token def http_post_form(url: str, form: dict[str, str], headers: dict) -> tuple[int | None, str, dict | None]: data = urllib.parse.urlencode(form).encode("utf-8") ctx = ssl._create_unverified_context() # 忽略面板自签证书错误 try: req = urllib.request.Request(url=url, data=data, method="POST") for k, v in headers.items(): req.add_header(k, v) with urllib.request.urlopen(req, context=ctx, timeout=60) as resp: body = resp.read().decode("utf-8", errors="replace") return getattr(resp, "status", 200), body, json.loads(body) except Exception as e: return None, str(e), None # --- 主逻辑 --- def main() -> int: # 1. 获取环境变量 api_secret_key = os.getenv("API_KEY") or os.getenv("API_SECRET_KEY") panel_url = os.getenv("PANEL_URL", "").rstrip("/") sites = os.getenv("SITES") key_path = os.getenv("KEY_PATH") crt_path = os.getenv("CRT_PATH") if not all([api_secret_key, panel_url, sites, key_path, crt_path]): print("❌ 错误: 请确保 API_KEY, PANEL_URL, SITES, KEY_PATH, CRT_PATH 均已设置。", file=sys.stderr) return 1 # 2. 读取证书文件 try: with open(key_path, "r") as f: ssl_key_content = f.read() with open(crt_path, "r") as f: ssl_crt_content = f.read() except Exception as e: print(f"❌ 读取证书文件失败: {e}", file=sys.stderr) return 1 domains = [s.strip() for s in sites.split(",") if s.strip()] domains_json = json.dumps(domains, ensure_ascii=False) headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "User-Agent": "Certimate-Deployer"} print(f"-> 目标面板: {panel_url}") print(f"-> 目标站点: {domains_json}") # 3. 上传证书 print("1. 上传证书中...") upload_url, _, _ = add_auth_query(f"{panel_url}/v2/ssl_domain?action=upload_cert", api_secret_key) _, _, upload_json = http_post_form(upload_url, {"key": ssl_key_content, "cert": ssl_crt_content}, headers) if not upload_json or not upload_json.get("status"): print(f"❌ 上传失败: {upload_json}", file=sys.stderr) return 1 # 获取证书 Hash（宝塔 V2 接口逻辑） cert_hash = upload_json.get("message", {}).get("hash") if isinstance(upload_json.get("message"), dict) else None if not cert_hash: print(f"❌ 未能获取证书 Hash: {upload_json}", file=sys.stderr) return 1 print(f"✅ 证书上传成功 (Hash: {cert_hash})") # 4. 部署到站点 print("2. 应用证书到站点...") deploy_url, _, _ = add_auth_query(f"{panel_url}/v2/ssl_domain?action=cert_deploy_sites", api_secret_key) _, _, deploy_json = http_post_form(deploy_url, {"hash": cert_hash, "append": "1", "domains": domains_json}, headers) if deploy_json and deploy_json.get("status"): print(f"✅ 部署成功: {deploy_json.get('msg') or deploy_json.get('message')}") return 0 else: print(f"❌ 部署失败: {deploy_json}", file=sys.stderr) return 1 if __name__ == "__main__": sys.exit(main())第三步：在 Certimate 中配置部署在 Certimate 后台，添加一个新的部署配置或编辑现有配置。1. 选择部署方式选择 Shell 脚本 (或 SSH，取决于你的 Certimate 是运行在本地容器还是通过 SSH 连接远程服务器)。如果 Certimate 运行在 Docker 中 ：推荐使用 本地 (Local) 执行模式。如果需要远程连接 ：选择 SSH 并填写服务器连接信息。2. 设置环境变量 (Environment Variables)这是最关键的一步，你需要将第一步获取的宝塔信息填入环境变量中。变量名必填示例值 / 说明PANEL_URL是宝塔面板的完整地址，例如 http://192.168.1.100:8888API_KEY是在第一步中获取的宝塔 API 密钥SITES是要部署证书的网站域名（宝塔中创建的网站名）。多个域名用逗号分隔，例如 example.com,www.example.comKEY_PATH是Certimate 指定 path后，指向生成的 .key 文件路径CRT_PATH自动Certimate 指定 path后，指向生成的 .crt 文件路径3. 设置执行命令在 Certimate 的脚本输入框中，输入调用 Python 脚本的命令。假设你将脚本保存为 /data/scripts/deploy_aapanel.py，命令如下：# 确保脚本有执行权限 chmod +x /data/scripts/deploy_aapanel.py # 执行脚本 # Certimate 会将证书路径通过环境变量传入，脚本直接读取即可 python3 /data/scripts/deploy_aapanel.py❓常见问题 (FAQ)Q: 为什么上传成功了，但是部署失败？A: 请确保 SITES 变量中填写的域名 已经在宝塔面板中创建 。宝塔无法向不存在的站点部署证书。Q: 脚本报错 urllib.error.HTTPError: HTTP Error 401: Unauthorized？A: 这通常意味着 API Key 错误，或者服务器时间与宝塔面板服务器时间相差太大（导致签名验证失败）。请同步两端服务器的时间。Q: 我的面板开启了 SSL (HTTPS)，PANEL_URL 怎么填？A: 如果面板地址是 HTTPS 的，请确保 URL 以 https:// 开头。脚本中包含了 ssl._create_unverified_context()，所以即使用户自签名的面板证书也是可以正常连接的。
The English version will be available after the Chinese version:uinetd：更現代的 rinetd 替代品uinetd 是一個輕量、現代的端口轉發服務，目標是成為 rinetd 的即插即用替代品，同時提供 rinetd 缺失的 UDP 轉發能力，(比如 支持 IPv4 與 IPv6 互相端口轉發）。並在 IPv6、可觀測性與易用性方面做了增強。它保持了與 rinetd 相近的配置格式，遷移成本很低。為什麼替換 rinetdUDP 支持 ：傳統 rinetd 通常只做 TCP 轉發，uinetd 同時支持 TCP/UDP/雙協議。IPv6 友好 ：原生支持 IPv4 與 IPv6 互相端口轉發。更易用的发行 ：单一二进制、支持打包为 deb/rpm。低改动迁移 ：配置格式与 rinetd 接近，仅新增“协议”一列。主要特性协议支持 ：tcp、udp、both/all（同时启两个监听）IPv4/IPv6 ：靈活的地址格式，IPv6 使用 2001:db8::1、[2001:db8::1]轻量单文件 ：无外部依赖，部署简单清晰日志 ：可配置 loglevel，便于排障最小可用配置编辑 /etc/uinetd.conf（与 rinetd 类似，结尾多一列“协议”）：# bindaddr bindport connectaddr connectport protocol 0.0.0.0 8080 127.0.0.1 80 tcp 0.0.0.0 53 1.1.1.1 53 udp [::] 443 [2001:db8::1] 8443 both # 日志等级：1=错误，2=简要，3=阻止日志+错误，4=连接明细+错误 loglevel 1启动：uinetd -c /etc/uinetd.conf可选 systemd（简化示例）：[Unit] Description=uinetd - internet redirection server After=network.target [Service] ExecStart=/usr/local/bin/uinetd -c /etc/uinetd.conf Restart=on-failure [Install] WantedBy=multi-user.target從 rinetd 平滑遷移新增協議列 ：rinetd 的四列規則，遷移到 uinetd 時在末尾加上協議即可。例：0.0.0.0 8080 127.0.0.1 80 → 0.0.0.0 8080 127.0.0.1 80 tcp同時轉發 TCP+UDP ：把協議寫為 both 或 all。IPv6 ：使用方括號，如 [::]、[2001:db8::1]。域名 ：目標地址可直接使用域名。常見用例DNS 代理（UDP） ：0.0.0.0 53 1.1.1.1 53 udpWeb 反向轉發（TCP） ：0.0.0.0 8080 127.0.0.1 80 tcpIPv6→IPv6（both） ：[::] 443 [2001:db8::1] 8443 both總結如果你在尋找一個與 rinetd 體驗相近、卻能原生支持 UDP/IPv6、並具備更好包發行與可觀測性的工具，uinetd 是一個穩妥的現代替代方案。歡迎試用並在生產環境中逐步替換現有 rinetd 配置。項目地址 ：GitHub 倉庫uinetd: A More Modern Alternative to rinetduinetd is a lightweight, modern port forwarding service designed to be a plug-and-play replacement for rinetd, while also providing UDP forwarding capabilities that rinetd lacks (such as native IPv4 and IPv6 mutual port forwarding). It enhances IPv6 support, observability, and usability. It maintains a similar configuration format to rinetd, making migration easy and low-cost.Why Replace rinetdUDP Support : Traditional rinetd typically only forwards TCP. uinetd supports TCP, UDP, and dual-protocol forwarding.IPv6 Friendly : Native support for IPv4 to IPv6 port forwarding and vice versa.Easier Distribution : Single binary, supports packaging as deb/rpm.Low Migration Effort : Configuration format remains close to rinetd, only adding a "protocol" column.Key FeaturesProtocol Support : tcp, udp, both/all (starts two listeners simultaneously)IPv4/IPv6 : Flexible address formats; IPv6 can be specified as 2001:db8::1 or [2001:db8::1]Lightweight Single File : No external dependencies, straightforward deploymentClear Logging : Configurable loglevel for easy troubleshootingMinimal Working ConfigurationEdit /etc/uinetd.conf (similar to rinetd but with an extra protocol column):# bindaddr bindport connectaddr connectport protocol 0.0.0.0 8080 127.0.0.1 80 tcp 0.0.0.0 53 1.1.1.1 53 udp [::] 443 [2001:db8::1] 8443 both # 日志等级：1=错误，2=简要，3=阻止日志+错误，4=连接明细+错误 loglevel 1Start:[Unit] Description=uinetd - internet redirection server After=network.target [Service] ExecStart=/usr/local/bin/uinetd -c /etc/uinetd.conf Restart=on-failure [Install] WantedBy=multi-user.target Smooth Migration from rinetdAdd Protocol Column : rinetd’s four-column rules become five columns by adding protocol.Example: 0.0.0.0 8080 127.0.0.1 80 → 0.0.0.0 8080 127.0.0.1 80 tcpTCP+UDP Forwarding : Use both or all as the protocol.IPv6 Support : Use brackets for IPv6 addresses like [::] or [2001:db8::1].Hostnames : Destination address can use domain names directly.Common Use CasesDNS Proxy (UDP) : 0.0.0.0 53 1.1.1.1 53 udpWeb Reverse Proxy (TCP) : 0.0.0.0 8080 127.0.0.1 80 tcpIPv6 to IPv6 (both) : [::] 443 [2001:db8::1] 8443 bothConclusionIf looking for a tool that provides a rinetd-like experience with native UDP and IPv6 support, improved packaging, and better observability, uinetd is a reliable modern replacement. It is recommended to try it and gradually migrate existing rinetd configurations in production environments.Project URL : GitHub Repository
引言最开始的时候，论文无法显示中文:本着"亲自指挥，亲自部署(SaaS)"的原则，以及 LaTeX 在 Overleaf 端不是很支持中文字体，并且有很多的编译限制，协作功能也存在问题。因此，在 Kubernetes 集群上部署一个自托管的 ShareLaTeX 来实现多用户同时使用。本项目不仅提供了完整的部署方案，还配置了 GitHub Actions CI/CD 流程，实现每日自动构建包含中文字体支持的 Docker 镜像。主要的痛点GitHub Actions 自动化构建：每周自动构建 Docker 镜像，实时更新最新的 Overleaf中文支持：集成 fandol 字体和完整的 TeX Live 中文包，及宋体，仿宋等中文环境云原生架构：基于 Kubernetes 的高可用部署容器化部署：使用 Helm Charts 简化部署过程架构概览ShareLaTeX 由三个核心组件构成：Redis：缓存和会话存储MongoDB：文档和用户数据存储ShareLaTeX：主应用服务（包含中文字体支持）开始部署准备环境1. 安装 Bitnami Helm Repository前两个组件（Redis 和 MongoDB）已经有 Bitnami 提供的稳定镜像，我们直接使用 Helm 安装：# 添加 bitnami repo helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update2. 创建命名空间kubectl create namespace latex部署数据层2.1 部署 MongoDB创建 values-mongodb.yaml 配置文件：auth: ## 启用认证 enabled: true ## MongoDB root 用户 rootUser: root ## MongoDB root 密码（建议使用 Secret 管理） rootPassword: "your-secure-password" ## 自定义用户和数据库 usernames: ["sharelatex"] passwords: ["sharelatex-password"] databases: ["sharelatex"] # 持久化存储配置 persistence: enabled: true size: 10Gi # 副本集配置（高可用） replicaCount: 2 architecture: replicaset # 外部访问配置（可选，用于调试） externalAccess: enabled: true service: type: LoadBalancer autoDiscovery: enabled: true # RBAC 配置 serviceAccount: create: true automountServiceAccountToken: true rbac: create: true部署 MongoDB：helm install mongo-mongodb bitnami/mongodb \ --namespace latex \ --values values-mongodb.yaml2.2 部署 Redis创建 values-redis.yaml 配置文件：global: redis: password: "your-redis-password"部署 Redis：helm install redis-master bitnami/redis \ --namespace latex \ --values values-redis.yaml部署应用层3.1 自定义 ShareLaTeX 镜像我们的项目提供了一个增强版的 ShareLaTeX 镜像，包含仿宋等常见中文论文场景的中文字体支持。如果需要其他字体，可以留言给我，我可以酌情添加.Dockerfile 特点：FROM sharelatex/sharelatex:latest # 设置环境变量避免交互式安装 ENV DEBIAN_FRONTEND=noninteractive # 安装中文字体和 TeX Live 包 RUN apt-get update && apt-get install -y \ latex-cjk-all \ texlive-lang-chinese \ texlive-lang-english \ git \ && rm -rf /var/lib/apt/lists/* # 安装中文字体库 RUN git clone https://github.com/Haixing-Hu/latex-chinese-fonts \ /usr/share/fonts/opentype/latex-chinese-fonts -b master # 更新字体缓存 RUN fc-cache -fv # 配置 TeX Live 并安装完整包 RUN tlmgr update --self && \ tlmgr install fandol && \ tlmgr install scheme-full3.2 使用自动构建的镜像项目配置了 GitHub Actions，每日自动构建镜像：# 拉取最新的每日构建镜像 docker pull ghcr.io/evsio0n/sharelatex-helm/sharelatex-custom:$(date +%Y%m%d)3.3 配置 ShareLaTeX创建 configmap-sharelatex.yaml：apiVersion: v1 kind: ConfigMap metadata: namespace: latex name: sharelatex-config data: OVERLEAF_SITE_URL: https://overleaf.your-domain.com OVERLEAF_BEHIND_PROXY: "true" EMAIL_CONFIRMATION_DISABLED: "true" # 禁用邮箱验证 ENABLE_CONVERSIONS: "true" ENABLED_LINKED_FILE_TYPES: project_file,project_output_file EXTERNAL_AUTH: none OVERLEAF_APP_NAME: "Your Lab Overleaf" # 自定义名称 OVERLEAF_MONGO_URL: mongodb://sharelatex:sharelatex-password@mongo-mongodb-headless.latex.svc.cluster.local/sharelatex OVERLEAF_REDIS_HOST: redis-master.latex.svc.cluster.local REDIS_HOST: redis-master.latex.svc.cluster.local REDIS_PORT: "6379" REDIS_PASSWORD: "your-redis-password"应用配置：kubectl apply -f configmap-sharelatex.yaml3.4 部署 ShareLaTeX 应用创建 overleaf-deployment.yaml：apiVersion: apps/v1 kind: Deployment metadata: name: overleaf namespace: latex spec: replicas: 1 selector: matchLabels: app: overleaf template: metadata: labels: app: overleaf spec: nodeSelector: kubernetes.io/arch: amd64 # 确保调度到 amd64 节点 containers: - name: overleaf image: ghcr.io/evsio0n/sharelatex-helm/sharelatex-custom:latest envFrom: - configMapRef: name: sharelatex-config ports: - containerPort: 80 resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "4Gi" cpu: "2000m" livenessProbe: httpGet: path: /status port: 80 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: httpGet: path: /status port: 80 initialDelaySeconds: 30 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: overleaf namespace: latex spec: selector: app: overleaf ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP部署应用：kubectl apply -f overleaf-deployment.yaml配置入口访问4.1 使用 Ingress（推荐）创建 ingress.yaml：略，这部分使用你们云服务商的Ingress4.2 使用 LoadBalancer如果你的集群支持 LoadBalancer：kubectl patch svc overleaf -n latex -p '{"spec": {"type": "LoadBalancer"}}'GitHub Actions CI/CD 流程项目包含完整的自动化构建流程：触发条件每日构建：每天 UTC 时间 02:00（北京时间 10:00）代码推送：当 Dockerfile 或构建配置发生变化时手动触发：在 GitHub Actions 页面手动触发构建产物Docker 镜像：推送到 GitHub Container Registry构建报告：详细的构建日志和包信息Artifacts：压缩的镜像文件供下载本地开发和测试项目提供了便捷的管理脚本：# 查看帮助 ./docker-manage.sh help # 本地构建镜像 ./docker-manage.sh build # 测试镜像 ./docker-manage.sh test # 查看状态 ./docker-manage.sh status # 调试构建问题 ./docker-manage.sh debug验证部署检查服务状态# 检查 Pod 状态 kubectl get pods -n latex # 检查服务 kubectl get svc -n latex # 查看日志 kubectl logs -f deployment/overleaf -n latex访问应用通过 Ingress 访问：https://overleaf.your-domain.com或通过端口转发测试：kubectl port-forward svc/overleaf 8080:80 -n latex然后访问：http://localhost:8080测试中文支持创建一个新项目并测试以下 LaTeX 代码：\documentclass{article} \usepackage{ctex} \usepackage{fontspec} \begin{document} \title{中文测试文档} \author{测试用户} \date{\today} \maketitle \section{中文章节} 这是一个中文测试段落。ShareLaTeX 现在支持中文字体了！ \subsection{数学公式} $$E = mc^2$$ \subsection{列表} \begin{itemize} \item 第一项 \item 第二项 \item 第三项 \end{itemize} \end{document}运维和监控日志监控# 查看应用日志 kubectl logs -f deployment/overleaf -n latex # 查看 MongoDB 日志 kubectl logs -f deployment/mongo-mongodb -n latex # 查看 Redis 日志 kubectl logs -f deployment/redis-master -n latex扩缩和编排MongoDB# 扩展 ShareLaTeX 实例 kubectl scale deployment overleaf --replicas=3 -n latex # 扩展 MongoDB 副本 helm upgrade mongo-mongodb bitnami/mongodb \ --namespace latex \ --set replicaCount=3 \ --values values-mongodb.yaml备份策略MongoDB 备份# 创建备份作业 kubectl create job --from=cronjob/mongodb-backup mongodb-backup-$(date +%Y%m%d) -n latex数据恢复# 从备份恢复（示例） kubectl exec -it mongo-mongodb-0 -n latex -- mongorestore --uri="mongodb://root:password@localhost:27017/sharelatex"故障排除常见问题中文字体显示问题# 检查字体安装 kubectl exec -it deployment/overleaf -n latex -- fc-list | grep -i chinese编译超时# 增加资源限制 kubectl patch deployment overleaf -n latex --patch='{"spec":{"template":{"spec":{"containers":[{"name":"overleaf","resources":{"limits":{"memory":"8Gi","cpu":"4000m"}}}]}}}}'数据库连接问题# 检查网络连接 kubectl exec -it deployment/overleaf -n latex -- curl mongo-mongodb-headless.latex.svc.cluster.local:27017参考资源ShareLaTeX GitHub RepositoryBitnami MongoDB Helm ChartBitnami Redis Helm ChartLaTeX Chinese Fonts项目 GitHub Repository在 Kubernetes 环境部署 Overleaf 2025
Step-by-Step Upgrade Workflow### STEP 1: BACKUP CURRENT DATABASE # Connect to existing container docker compose exec plausible_db bash # Internal dump to container volume pg_dumpall -U postgres > /var/lib/postgresql/backup.sql # Exit container exit ### STEP 2: EXTRACT BACKUP FROM VOLUME # Copy SQL backup to host via docker compose cp docker compose cp db:/var/lib/postgresql/backup.sql ./backup_$(date +%F).sql ### STEP 3: MIGRATE TO NEW CONTAINER # Verify backup integrity before migration head -n 20 backup_*.sql # Check header # Update compose.yaml image tag version: '3.8' services: plausible_db: image: postgres:16-version # Updated here assume you upgrade to pg16 # Launch new container docker compose up -d db # Insert backup into new container docker compose cp backup_date.sql db:/restore.sql # Execute under db docker compose exec -it db cat restore.sql | psql -U postgres exit docker compose down && docker compose up🔧 Best Practicesgraph TD A[Stop Services] --> B[pg_dumpall Backup] B --> C[Spin up New Container] C --> D[Restore Backup] D --> E[Test Compatibility] E --> F[Update compose.yaml] F --> G[Restart Stack]🔍 Pro TipsUse ephemeral containers for testing migrations:docker run --rm -v $(pwd)/backup.sql:/backup.sql postgres:15 \ bash -c "psql -U postgres -f /backup.sql"After migrate, make sure delete old volumes incase redundated file!💡 Key Resources:Official PostgreSQL Upgrade GuideDocker Postgres Image Docspg_upgrade Deep DiveTest your upgrade in staging first!
Intergrate linux and mikrotik gre tunnel with keepalive
啟動 ping-endpoint.timer:[Unit] Description=Timer to ping endpoint every 10s after network is up BindsTo=sys-subsystem-net-devices-eth0.device After=sys-subsystem-net-devices-eth0.device [Timer] OnActiveSec=0 OnUnitActiveSec=10s Unit=ping-endpoint.service [Install] WantedBy=timers.target啟動 ping-endpoint.service:[Unit] Description=Ping specified endpoint After=network.target network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/usr/bin/ping -c 1 [ENDPOINT IP] SuccessExitStatus=0 1 2sudo systemctl daemon-reload sudo systemctl enable --now ping-endpoint.timer
首先，安装 SGLang。可以通过以下命令安装：pip install uv pip install "sglang[all]>=0.4.3" --find-links https://flashinfer.ai/whl/cu124/torch2.5/flashinfer-python -i https://pypi.tuna.tsinghua.edu.cn/simple模型文件需要从 deepseek-ai/DeepSeek-R1 下载，假设放在 /mnt/models/DeepSeek-R1。初始尝试和问题第一次启动服务器时，使用以下命令：python3 -m sglang.launch_server \ --model /mnt/models/DeepSeek-R1 \ --tp 8 \ --dtype auto \ --trust-remote-code \ --enable-torch-compile \ --disable-cuda-graph \ --mem-fraction-static 0.7 \ --served-model-name deepseek --api-key 123但遇到错误：RuntimeError: expected mat1 and mat2 to have the same dtype, but got: c10::BFloat16 != c10::Half这是因为 DeepSeek-R1 使用混合数据类型（如 BFloat16 和 F8_E4M3），而 --dtype half 强制转换为 float16，导致不兼容。解决问题通过将 --dtype 改为 auto，问题解决：python3 -m sglang.launch_server \ --model /mnt/models/DeepSeek-R1 \ --tp 8 \ --dtype auto \ --trust-remote-code \ --enable-torch-compile \ --disable-cuda-graph \ --mem-fraction-static 0.7 \ --served-model-name deepseek --api-key 123解决问题通过将 --dtype 改为 auto，问题解决：python3 -m sglang.launch_server \ --model /mnt/models/DeepSeek-R1 \ --tp 8 \ --dtype auto \ --trust-remote-code \ --enable-torch-compile \ --disable-cuda-graph \ --mem-fraction-static 0.7 \ --served-model-name deepseek --api-key 123这允许模型以原始数据类型加载，成功启动 sglang。性能优化为加快 token 生成，建议启用推测解码，设置如下：--speculative-num-steps 3--speculative-num-draft-tokens 4--mem-fraction-static 0.7--schedule-conservativeness 0.01在issue中， 低并发（如 1 个请求）时可达到每秒 65 token 的速度。参考性能优化策略基于 issue #4616 和相关讨论，以下是影响 token 生成速度的关键参数：参数描述/影响推荐值/注意事项已知问题--speculative-algorithm启用 Next-N 推测解码，生成草稿 token 树，减少前向传递次数设置为 "NEXTN"高并发（>32）时性能下降--speculative-num-steps推测解码步骤数，影响吞吐量推荐 3，测试显示最高吞吐量---speculative-num-draft-tokens草稿 token 数量，影响性能推荐 4，测试显示最佳性能---speculative-eagle-topkEAGLE策略的 top-k 值，影响推测解码效率推荐 1---speculative-draft草稿模型目录，需指定正确路径设置为 ``---mem-fraction-static静态内存分配比例，防止 OOM 错误推荐 0.7---schedule-conservativeness调度保守性，影响吞吐量推荐 0.01，高性能设置-CUDA Graph减少内核启动开销和同步延迟，提升推理性能，增加内存使用默认启用，可用 --disable-cuda-graph 禁用，参数 --cuda-graph-max-bs: 160, 512, 1024与 DP-Attention 和 dp-size >4 可能导致 CUDA 错误Torch Compile将 PyTorch 模型转换为优化执行图，提升 GPU 性能用 --enable-torch-compile 启用，默认禁用，DeepSeek-R1 捕获时间约 1 小时，Next-N 约 5 分钟-参考jupyter 脚本:pip install uv pip install "sglang[all]>=0.4.3" --find-links https://flashinfer.ai/whl/cu124/torch2.5/flashinfer-python -i https://pypi.tuna.tsinghua.edu.cn/simple python3 -m sglang.launch_server \ --model /mnt/models/DeepSeek-R1 \ --tp 8 \ --trust-remote-code \ --enable-ep-moe \ --mem-fraction-static 0.7 \ --schedule-conservativeness 0.01 \ --served-model-name deepseek --api-key 123参考输出:2025-03-22 15:09:20.381293: I tensorflow/core/util/port.cc:111] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`. 2025-03-22 15:09:20.384090: I tensorflow/tsl/cuda/cudart_stub.cc:28] Could not find cuda drivers on your machine, GPU will not be used. 2025-03-22 15:09:20.418164: E tensorflow/compiler/xla/stream_executor/cuda/cuda_dnn.cc:9342] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered 2025-03-22 15:09:20.418198: E tensorflow/compiler/xla/stream_executor/cuda/cuda_fft.cc:609] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered 2025-03-22 15:09:20.418236: E tensorflow/compiler/xla/stream_executor/cuda/cuda_blas.cc:1518] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered 2025-03-22 15:09:20.425708: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: AVX2 AVX512F AVX512_VNNI AVX512_BF16 AVX_VNNI AMX_TILE AMX_INT8 AMX_BF16 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags. 2025-03-22 15:09:21.048490: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT INFO 03-22 15:09:22 __init__.py:190] Automatically detected platform cuda. [2025-03-22 15:09:33] server_args=ServerArgs(model_path='/mnt/models/DeepSeek-R1', tokenizer_path='/mnt/models/DeepSeek-R1', tokenizer_mode='auto', skip_tokenizer_init=False, load_format='auto', trust_remote_code=True, dtype='auto', kv_cache_dtype='auto', quantization=None, quantization_param_path=None, context_length=None, device='cuda', served_model_name='deepseek', chat_template=None, is_embedding=False, revision=None, host='127.0.0.1', port=30000, mem_fraction_static=0.7, max_running_requests=None, max_total_tokens=None, chunked_prefill_size=8192, max_prefill_tokens=16384, schedule_policy='fcfs', schedule_conservativeness=0.01, cpu_offload_gb=0, page_size=1, tp_size=8, stream_interval=1, stream_output=False, random_seed=286257988, constrained_json_whitespace_pattern=None, watchdog_timeout=300, dist_timeout=None, download_dir=None, base_gpu_id=0, gpu_id_step=1, log_level='info', log_level_http=None, log_requests=False, log_requests_level=0, show_time_cost=False, enable_metrics=False, decode_log_interval=40, api_key='123', file_storage_path='sglang_storage', enable_cache_report=False, reasoning_parser=None, dp_size=1, load_balance_method='round_robin', ep_size=8, dist_init_addr=None, nnodes=1, node_rank=0, json_model_override_args='{}', lora_paths=None, max_loras_per_batch=8, lora_backend='triton', attention_backend='flashinfer', sampling_backend='flashinfer', grammar_backend='outlines', speculative_algorithm=None, speculative_draft_model_path=None, speculative_num_steps=5, speculative_eagle_topk=4, speculative_num_draft_tokens=8, speculative_accept_threshold_single=1.0, speculative_accept_threshold_acc=1.0, speculative_token_map=None, enable_double_sparsity=False, ds_channel_config_path=None, ds_heavy_channel_num=32, ds_heavy_token_num=256, ds_heavy_channel_type='qk', ds_sparse_decode_threshold=4096, disable_radix_cache=False, disable_cuda_graph=False, disable_cuda_graph_padding=False, enable_nccl_nvls=False, disable_outlines_disk_cache=False, disable_custom_all_reduce=False, disable_mla=False, disable_overlap_schedule=False, enable_mixed_chunk=False, enable_dp_attention=False, enable_ep_moe=True, enable_torch_compile=False, torch_compile_max_bs=32, cuda_graph_max_bs=160, cuda_graph_bs=None, torchao_config='', enable_nan_detection=False, enable_p2p_check=False, triton_attention_reduce_in_fp32=False, triton_attention_num_kv_splits=8, num_continuous_decode_steps=1, delete_ckpt_after_loading=False, enable_memory_saver=False, allow_auto_truncate=False, enable_custom_logit_processor=False, tool_call_parser=None, enable_hierarchical_cache=False, enable_flashinfer_mla=False, flashinfer_mla_disable_ragged=False, warmups=None, debug_tensor_dump_output_folder=None, debug_tensor_dump_input_file=None, debug_tensor_dump_inject=False) INFO 03-22 15:09:39 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:39 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:39 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. INFO 03-22 15:09:40 __init__.py:190] Automatically detected platform cuda. [2025-03-22 15:09:43 TP5] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:43 TP5] Init torch distributed begin. [2025-03-22 15:09:45 TP0] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:45 TP0] Init torch distributed begin. [2025-03-22 15:09:46 TP1] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:46 TP1] Init torch distributed begin. [2025-03-22 15:09:46 TP3] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:46 TP3] Init torch distributed begin. [2025-03-22 15:09:47 TP7] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:47 TP7] Init torch distributed begin. [2025-03-22 15:09:47 TP6] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:47 TP6] Init torch distributed begin. [2025-03-22 15:09:47 TP4] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:47 TP4] Init torch distributed begin. [2025-03-22 15:09:47 TP2] MLA optimization is turned on. Use triton backend. [2025-03-22 15:09:47 TP2] Init torch distributed begin. [2025-03-22 15:09:48 TP0] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP1] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP2] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP4] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP3] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP6] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP5] sglang is using nccl==2.21.5 [2025-03-22 15:09:48 TP7] sglang is using nccl==2.21.5 [2025-03-22 15:09:52 TP7] Init torch distributed ends. mem usage=1.50 GB [2025-03-22 15:09:52 TP2] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP4] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP1] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP5] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP7] Load weight begin. avail mem=137.80 GB [2025-03-22 15:09:52 TP2] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP3] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP4] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP1] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP5] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP3] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP0] Init torch distributed ends. mem usage=1.87 GB [2025-03-22 15:09:52 TP0] Load weight begin. avail mem=137.42 GB [2025-03-22 15:09:52 TP6] Init torch distributed ends. mem usage=1.97 GB [2025-03-22 15:09:52 TP6] Load weight begin. avail mem=137.33 GB [2025-03-22 15:09:52 TP2] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP4] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP1] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP7] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP0] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP6] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP3] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP5] The following error message 'operation scheduled before its operands' can be ignored. [2025-03-22 15:09:52 TP4] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP7] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP3] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP2] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP6] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP0] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP1] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. [2025-03-22 15:09:52 TP5] Detected fp8 checkpoint. Please note that the format is experimental and subject to change. Loading safetensors checkpoint shards: 0% Completed | 0/163 [00:00<?, ?it/s] Loading safetensors checkpoint shards: 1% Completed | 1/163 [00:00<00:43, 3.70it/s] Loading safetensors checkpoint shards: 2% Completed | 4/163 [00:00<00:22, 7.00it/s] Loading safetensors checkpoint shards: 4% Completed | 6/163 [00:00<00:17, 9.10it/s] Loading safetensors checkpoint shards: 5% Completed | 8/163 [00:01<00:22, 7.00it/s] Loading safetensors checkpoint shards: 6% Completed | 9/163 [00:01<00:25, 6.08it/s] Loading safetensors checkpoint shards: 7% Completed | 11/163 [00:01<00:23, 6.57it/s] Loading safetensors checkpoint shards: 7% Completed | 12/163 [00:01<00:21, 6.96it/s] Loading safetensors checkpoint shards: 8% Completed | 13/163 [00:01<00:24, 6.15it/s] Loading safetensors checkpoint shards: 10% Completed | 16/163 [00:02<00:19, 7.50it/s] Loading safetensors checkpoint shards: 11% Completed | 18/163 [00:02<00:19, 7.40it/s] Loading safetensors checkpoint shards: 13% Completed | 22/163 [00:02<00:12, 11.41it/s] Loading safetensors checkpoint shards: 15% Completed | 24/163 [00:02<00:13, 10.00it/s] Loading safetensors checkpoint shards: 16% Completed | 26/163 [00:03<00:14, 9.37it/s] Loading safetensors checkpoint shards: 17% Completed | 28/163 [00:03<00:15, 8.92it/s] Loading safetensors checkpoint shards: 19% Completed | 31/163 [00:03<00:11, 11.61it/s] Loading safetensors checkpoint shards: 20% Completed | 33/163 [00:04<00:18, 7.19it/s] Loading safetensors checkpoint shards: 21% Completed | 35/163 [00:04<00:19, 6.44it/s] Loading safetensors checkpoint shards: 24% Completed | 39/163 [00:04<00:12, 9.56it/s] Loading safetensors checkpoint shards: 26% Completed | 42/163 [00:05<00:12, 9.75it/s] Loading safetensors checkpoint shards: 27% Completed | 44/163 [00:05<00:10, 10.91it/s] Loading safetensors checkpoint shards: 28% Completed | 46/163 [00:05<00:16, 7.22it/s] Loading safetensors checkpoint shards: 31% Completed | 50/163 [00:05<00:10, 10.95it/s] Loading safetensors checkpoint shards: 33% Completed | 54/163 [00:05<00:07, 13.97it/s] Loading safetensors checkpoint shards: 36% Completed | 58/163 [00:06<00:07, 13.26it/s] Loading safetensors checkpoint shards: 37% Completed | 60/163 [00:06<00:08, 11.68it/s] Loading safetensors checkpoint shards: 38% Completed | 62/163 [00:06<00:10, 9.71it/s] Loading safetensors checkpoint shards: 41% Completed | 67/163 [00:06<00:06, 14.87it/s] Loading safetensors checkpoint shards: 43% Completed | 70/163 [00:07<00:09, 9.66it/s] Loading safetensors checkpoint shards: 44% Completed | 72/163 [00:08<00:12, 7.41it/s] Loading safetensors checkpoint shards: 45% Completed | 74/163 [00:08<00:12, 7.00it/s] Loading safetensors checkpoint shards: 48% Completed | 79/163 [00:08<00:09, 8.88it/s] Loading safetensors checkpoint shards: 50% Completed | 81/163 [00:09<00:12, 6.64it/s] Loading safetensors checkpoint shards: 52% Completed | 84/163 [00:09<00:10, 7.38it/s] Loading safetensors checkpoint shards: 53% Completed | 86/163 [00:09<00:09, 8.41it/s] Loading safetensors checkpoint shards: 54% Completed | 88/163 [00:10<00:11, 6.79it/s] Loading safetensors checkpoint shards: 55% Completed | 89/163 [00:10<00:10, 6.95it/s] Loading safetensors checkpoint shards: 55% Completed | 90/163 [00:10<00:12, 5.91it/s] Loading safetensors checkpoint shards: 56% Completed | 91/163 [00:11<00:14, 5.13it/s] Loading safetensors checkpoint shards: 57% Completed | 93/163 [00:11<00:12, 5.53it/s] Loading safetensors checkpoint shards: 58% Completed | 95/163 [00:11<00:10, 6.63it/s] Loading safetensors checkpoint shards: 59% Completed | 96/163 [00:11<00:11, 5.64it/s] Loading safetensors checkpoint shards: 61% Completed | 100/163 [00:11<00:06, 10.14it/s] Loading safetensors checkpoint shards: 63% Completed | 103/163 [00:12<00:05, 10.43it/s] Loading safetensors checkpoint shards: 64% Completed | 105/163 [00:12<00:08, 6.90it/s] Loading safetensors checkpoint shards: 66% Completed | 107/163 [00:13<00:08, 6.58it/s] Loading safetensors checkpoint shards: 69% Completed | 112/163 [00:13<00:04, 11.18it/s] Loading safetensors checkpoint shards: 70% Completed | 114/163 [00:13<00:04, 10.48it/s] Loading safetensors checkpoint shards: 71% Completed | 116/163 [00:13<00:05, 8.91it/s] Loading safetensors checkpoint shards: 74% Completed | 120/163 [00:14<00:04, 9.64it/s] Loading safetensors checkpoint shards: 75% Completed | 122/163 [00:14<00:06, 6.76it/s] Loading safetensors checkpoint shards: 77% Completed | 125/163 [00:14<00:04, 8.68it/s] Loading safetensors checkpoint shards: 78% Completed | 127/163 [00:15<00:03, 9.79it/s] Loading safetensors checkpoint shards: 79% Completed | 129/163 [00:15<00:04, 6.98it/s] Loading safetensors checkpoint shards: 82% Completed | 133/163 [00:15<00:03, 8.19it/s] Loading safetensors checkpoint shards: 83% Completed | 135/163 [00:16<00:03, 7.59it/s] Loading safetensors checkpoint shards: 83% Completed | 136/163 [00:16<00:04, 6.40it/s] Loading safetensors checkpoint shards: 84% Completed | 137/163 [00:16<00:04, 5.72it/s] Loading safetensors checkpoint shards: 85% Completed | 139/163 [00:17<00:04, 5.93it/s] Loading safetensors checkpoint shards: 87% Completed | 142/163 [00:17<00:03, 6.18it/s] Loading safetensors checkpoint shards: 89% Completed | 145/163 [00:17<00:02, 7.12it/s] Loading safetensors checkpoint shards: 91% Completed | 148/163 [00:18<00:01, 7.55it/s] Loading safetensors checkpoint shards: 93% Completed | 152/163 [00:18<00:01, 10.47it/s] Loading safetensors checkpoint shards: 94% Completed | 154/163 [00:18<00:01, 8.80it/s] Loading safetensors checkpoint shards: 96% Completed | 157/163 [00:19<00:00, 8.68it/s] Loading safetensors checkpoint shards: 98% Completed | 159/163 [00:19<00:00, 7.81it/s] Loading safetensors checkpoint shards: 99% Completed | 161/163 [00:19<00:00, 7.43it/s] Loading safetensors checkpoint shards: 100% Completed | 163/163 [00:19<00:00, 8.85it/s] Loading safetensors checkpoint shards: 100% Completed | 163/163 [00:19<00:00, 8.20it/s] [2025-03-22 15:10:14 TP7] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=58.21 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP2] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP6] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP5] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP4] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP3] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP1] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.74 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP0] Load weight end. type=DeepseekV3ForCausalLM, dtype=torch.bfloat16, avail mem=57.83 GB, mem usage=79.59 GB. [2025-03-22 15:10:14 TP7] Memory pool end. avail mem=40.63 GB [2025-03-22 15:10:14 TP3] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP2] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP4] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP0] Memory pool end. avail mem=40.26 GB [2025-03-22 15:10:14 TP1] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP6] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP5] Memory pool end. avail mem=40.16 GB [2025-03-22 15:10:14 TP7] Capture cuda graph begin. This can take up to several minutes. avail mem=40.54 GB [2025-03-22 15:10:14 TP2] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB [2025-03-22 15:10:14 TP4] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB [2025-03-22 15:10:14 TP0] Capture cuda graph begin. This can take up to several minutes. avail mem=40.16 GB [2025-03-22 15:10:14 TP3] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB Capturing batches (avail_mem=40.00 GB): 0%| | 0/23 [00:00<?, ?it/s][2025-03-22 15:10:14 TP1] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB [2025-03-22 15:10:14 TP6] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB [2025-03-22 15:10:14 TP5] Capture cuda graph begin. This can take up to several minutes. avail mem=40.07 GB [2025-03-22 15:10:16 TP0] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP5] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP3] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP1] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP7] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP4] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP6] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. [2025-03-22 15:10:16 TP2] Using configuration from /opt/conda/lib/python3.11/site-packages/sglang/srt/layers/quantization/configs/N=576,K=7168,device_name=NVIDIA_H200,dtype=fp8_w8a8,block_shape=[128, 128].json for W8A8 Block FP8 kernel. loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands loc("/opt/conda/lib/python3.11/site-packages/sglang/srt/layers/attention/triton_ops/decode_attention.py":310:16): error: operation scheduled before its operands Capturing batches (avail_mem=37.73 GB): 100%|███| 23/23 [00:38<00:00, 1.69s/it] [2025-03-22 15:10:53 TP0] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP1] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP3] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP6] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP2] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP4] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP7] Registering 2829 cuda graph addresses [2025-03-22 15:10:53 TP5] Registering 2829 cuda graph addresses [2025-03-22 15:10:54 TP3] Capture cuda graph end. Time elapsed: 39.46 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP1] Capture cuda graph end. Time elapsed: 39.46 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP7] Capture cuda graph end. Time elapsed: 39.48 s. avail mem=38.05 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP5] Capture cuda graph end. Time elapsed: 39.50 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP4] Capture cuda graph end. Time elapsed: 39.51 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP0] Capture cuda graph end. Time elapsed: 39.51 s. avail mem=37.68 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP6] Capture cuda graph end. Time elapsed: 39.51 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP2] Capture cuda graph end. Time elapsed: 39.51 s. avail mem=37.58 GB. mem usage=2.49 GB. [2025-03-22 15:10:54 TP6] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP0] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP7] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP1] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP4] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP3] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP2] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54 TP5] max_total_num_tokens=248994, chunked_prefill_size=8192, max_prefill_tokens=16384, max_running_requests=2049, context_len=163840 [2025-03-22 15:10:54] INFO: Started server process [71649] [2025-03-22 15:10:54] INFO: Waiting for application startup. [2025-03-22 15:10:54] INFO: Application startup complete. [2025-03-22 15:10:54] INFO: Uvicorn running on http://127.0.0.1:30000 (Press CTRL+C to quit) [2025-03-22 15:10:55] INFO: 127.0.0.1:50206 - "GET /get_model_info HTTP/1.1" 200 OK [2025-03-22 15:10:55 TP0] Prefill batch. #new-seq: 1, #new-token: 7, #cached-token: 0, token usage: 0.00, #running-req: 0, #queue-req: 0, [2025-03-22 15:10:59] INFO: 127.0.0.1:50220 - "POST /generate HTTP/1.1" 200 OK [2025-03-22 15:10:59] The server is fired up and ready to roll!参考引用GitHub - deepseek-ai/DeepSeek-R1deepseek-ai/DeepSeek-R1Server Arguments — SGLangSetting Data Type from the CLI interface · Issue #325 · sgl-project/sglangParameters for Fastest Token Generation · Issue #4616 · sgl-project/sglangA Simple Guide to DeepSeek R1: Architecture, Training, Local Deployment, and Hardware RequirementsDeepSeek R1 On-Prem Setup: Run Advanced AI Models on Your Hardware with SGLang
编译ELK过程OS: Debian sid/trixeapt install ant openjdk-8-jdk texinfo libboost-dev cmake选定 java8 来替代 jdk21sudo update-alternatives --config javaElasticsearchgit clone https://github.com/elastic/elasticsearch -b v8.16.1 --depth=1查看依赖version.properties检查依赖:确定 jna 版本 5.12.1git clone https://github.com/java-native-access/jna -b 5.12.1 --depth=1 ant distML-CPPgit clone https://github.com/elastic/ml-cpp/ -b v8.16.1 --depth=1WIP...
Issue Step CA Certificate with PromoxVE with ACME
Install Step CA Certificate with PromoxVE with ACMEPrerequisitesYou have already have a step ca running on your other devices.You used a FQDN(Fully Qualified Domain Name) for your step ca.Your Step CA can be accessiable to your ProxmoxVE server's FQDN.Step 1: Install CA CertificateUse step ca to get the root certificate.step ca root ca.crt ``Copy the root certificate to your ProxmoxVE server.scp ca.crt root@<ProxmoxVE-IP>:/root/On your ProxmoxVE server, move the root certificate to the correct location.mv /root/ca.crt /usr/local/share/ca-certificates/Update the CA certificates.update-ca-certificatesConfiguring ACME Directory URL to ProxmoxVEpvenode acme account register default <your email here> --directory https://your-acme-endpointSetup the fqdn and prepare to get the certificate.pvenode config set --acme domains=<ProxmoxVE-FQDN>Get the certificate.pvenode acme cert order
Forwarding unix socket to a tcp connection.
sock2tcpsock2tcp is a simple tool to forward a local socket to serve as a TCP server.It is useful when you have a local socket and you want to expose it to specific IP and port.Installationgo install github.com/evsio0n/sock2tcpUsageuse .env file to configure the serverParameterDescriptionUNIX_SOCKET_PATHThe path of the local socketTCP_BIND_ADDRESSThe port to expose the socketUNIX_SOCKET_PATH=/path/to/socket TCP_BIND_ADDRESS=0.0.0.0:8080use environment variables to configure the serverexport UNIX_SOCKET_PATH=/path/to/socket export TCP_BIND_ADDRESS=0.0.0.0:8080 ./sock2tcpuse docker container.docker run -v /tmp/mysql.sock:/tmp/mysql.sock -e "UNIX_SOCKET_PATH=/tmp/mysql.sock" -e "TCP_BIND_ADDRESS=0.0.0.0:3306" -p 3306 ghcr.io/evsio0n/sock2tcp:latest