AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/03 19:41 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds CPLD firmware upload and sysfs attributes for the ADVA x1 OCP Timecard, which is a physical PCIe device. The new code heavily relies on hardware-specific interactions (e.g., polling MMIO registers for MicroBlaze firmware grants, I2C communication with a PCA9548 mux and Lattice CPLD) that are not emulated in standard QEMU environments. Consequently, the core logic is unreachable during fuzzing without the physical hardware.",
  "WorthFuzzing": false
}

1/1 2026/08/03 19:41 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit b1c53476f5ea039ac1a344d1b990df9a4f95766a\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Aug 3 19:41:08 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/ABI/testing/sysfs-timecard b/Documentation/ABI/testing/sysfs-timecard\nindex 3ae41b7634ac9..f7c9955acb0a9 100644\n--- a/Documentation/ABI/testing/sysfs-timecard\n+++ b/Documentation/ABI/testing/sysfs-timecard\n@@ -11,6 +11,40 @@ Contact:\tJonathan Lemon \u003cjonathan.lemon@gmail.com\u003e\n Description:\tThis directory contains the attributes of the Nth timecard\n \t\tregistered.\n \n+What:\t\t/sys/class/timecard/ocpN/cpld_device_id\n+Date:\t\tJuly 2026\n+Contact:\tSagi Maimon \u003cmaimon.sagi@gmail.com\u003e\n+Description:\t(RO) The 32-bit Lattice device ID of the TAP CPLD, reported as\n+\t\ta hex string, e.g. \"0xe12bc043\".\n+\n+\t\tOnly present on ADVA x1 TAP boards (PCI ID 0xad5a:0x0410).\n+\t\tThe Lattice LCMXO3LF-210 reports 0xe12bc043.\n+\n+\t\tThe driver acquires the MicroBlaze I2C bus internally before\n+\t\tissuing the READ_IDCODE command; no bus arbitration is required\n+\t\tfrom userspace.\n+\n+What:\t\t/sys/class/timecard/ocpN/cpld_status\n+Date:\t\tJuly 2026\n+Contact:\tSagi Maimon \u003cmaimon.sagi@gmail.com\u003e\n+Description:\t(RO) The status register of the TAP CPLD, in human-readable\n+\t\tform:\n+\n+\t\t  done=\u003c0|1\u003e busy=\u003c0|1\u003e failed=\u003c0|1\u003e\n+\n+\t\tOnly present on ADVA x1 TAP boards (PCI ID 0xad5a:0x0410).\n+\n+\t\tdone=1 indicates the configuration flash was successfully\n+\t\tprogrammed and is active.  busy=1 means an internal operation\n+\t\tis in progress.  failed=1 means the last ISC operation failed.\n+\n+\t\tThe driver acquires the MicroBlaze I2C bus internally; no bus\n+\t\tarbitration is required from userspace.\n+\n+\t\tTo program new CPLD firmware use the standard kernel\n+\t\tfirmware-upload interface registered at:\n+\t\t/sys/class/firmware/adva-cpld/\n+\n What:\t\t/sys/class/timecard/ocpN/available_clock_sources\n Date:\t\tSeptember 2021\n Contact:\tJonathan Lemon \u003cjonathan.lemon@gmail.com\u003e\ndiff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c\nindex 35e911f1ad78c..db8ab161d4f0f 100644\n--- a/drivers/ptp/ptp_ocp.c\n+++ b/drivers/ptp/ptp_ocp.c\n@@ -24,6 +24,11 @@\n #include \u003clinux/nvmem-consumer.h\u003e\n #include \u003clinux/crc16.h\u003e\n #include \u003clinux/dpll.h\u003e\n+#include \u003clinux/unaligned.h\u003e\n+#include \u003clinux/delay.h\u003e\n+#include \u003clinux/firmware.h\u003e\n+#include \u003clinux/delay.h\u003e\n+#include \u003clinux/firmware.h\u003e\n \n #define PCI_DEVICE_ID_META_TIMECARD\t\t0x0400\n \n@@ -85,6 +90,7 @@ struct ptp_ocp_adva_info {\n \tu8\t\t\t\tsignals_nr;\n \tu8\t\t\t\tfreq_in_nr;\n \tconst struct ocp_attr_group\t*attr_groups;\n+\tbool\t\t\t\thas_cpld; /* x1: supports CPLD firmware upload */\n };\n \n #define OCP_CTRL_ENABLE\t\tBIT(0)\n@@ -163,7 +169,8 @@ struct gpio_reg {\n \tu32\tgpio1;\n \tu32\t__pad0;\n \tu32\tgpio2;\n-\tu32\t__pad1;\n+\t/* adva_x1: I2C bus ownership register; reserved on other variants */\n+\tu32\ti2c_bus_ctrl;\n };\n \n struct irig_master_reg {\n@@ -416,6 +423,12 @@ struct ptp_ocp {\n \tdpll_tracker tracker;\n \tint signals_nr;\n \tint freq_in_nr;\n+\t/* adva_x1 CPLD I2C (internal use only) */\n+\tstruct mutex\t\tcpld_lock;            /* serialises CPLD operations */\n+\tint\t\t\tcpld_i2c_adap_nr;     /* I2C adapter nr; -1 if absent */\n+\tstruct fw_upload\t*cpld_fw_upload;      /* firmware upload handle; NULL if absent */\n+\tbool\t\t\tcpld_cancel;          /* cancellation requested */\n+\tbool\t\t\tcpld_in_config_mode;  /* EN_CFG_TP issued but not yet REFRESH'd */\n };\n \n #define OCP_REQ_TIMESTAMP\tBIT(0)\n@@ -449,6 +462,8 @@ static int ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r);\n \n static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r);\n \n+static const struct fw_upload_ops adva_cpld_upload_ops;\n+\n static const struct ocp_sma_op ocp_adva_sma_op;\n static const struct ocp_sma_op ocp_adva_x1_sma_op;\n \n@@ -1273,6 +1288,7 @@ static struct ocp_resource ocp_adva_x1_resource[] = {\n \t\t\t.signals_nr   = 4,\n \t\t\t.freq_in_nr   = 4,\n \t\t\t.attr_groups  = adva_timecard_x1_groups,\n+\t\t\t.has_cpld     = true,\n \t\t},\n \t},\n \t{ }\n@@ -3197,6 +3213,20 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)\n \t\treturn err;\n \tptp_ocp_sma_init(bp);\n \n+\tif (info-\u003ehas_cpld) {\n+\t\tstruct fw_upload *fwl;\n+\n+\t\tfwl = firmware_upload_register(THIS_MODULE, \u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t\t       \"adva-cpld\",\n+\t\t\t\t\t       \u0026adva_cpld_upload_ops, bp);\n+\t\tif (IS_ERR(fwl))\n+\t\t\tdev_warn(\u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t \"CPLD firmware upload unavailable: %pe\\n\",\n+\t\t\t\t fwl);\n+\t\telse\n+\t\t\tbp-\u003ecpld_fw_upload = fwl;\n+\t}\n+\n \treturn ptp_ocp_init_clock(bp, \u0026info-\u003eservo);\n }\n \n@@ -4224,6 +4254,443 @@ static const struct ocp_attr_group art_timecard_groups[] = {\n \t{ },\n };\n \n+/*\n+ * Internal helpers for the adva_x1 TAP CPLD (Lattice LCMXO3LF-210).\n+ *\n+ * The CPLD sits at I2C address 0x40 behind a PCA9548 mux (0x74) on\n+ * channel 0.  The I2C bus is shared with the MicroBlaze firmware;\n+ * cpld_lock + mblaze acquire/release provide mutual exclusion for the\n+ * full duration of any CPLD operation.  No raw I2C access is exposed\n+ * to userspace; only the high-level attributes below are.\n+ */\n+\n+#define ADVA_MUX_ADDR     0x74\n+#define ADVA_CPLD_ADDR    0x40\n+#define ADVA_MUX_CHANNEL  0\n+\n+#define MBLAZE_REQUEST    0x0000aaaaU\n+#define MBLAZE_GRANTED    0x5555aaaaU\n+#define MBLAZE_RELEASE    0x55550000U\n+#define MBLAZE_RETRIES    200\n+#define MBLAZE_RETRY_US   10000\n+\n+/* Lattice LCMXO3LF ISC command codes */\n+#define CPLD_CMD_READ_ID      0xE0000000UL\n+#define CPLD_CMD_READ_STATUS  0x3C000000UL\n+#define CPLD_CMD_EN_CFG_TP    0x74   /* enable config, transparent mode */\n+#define CPLD_CMD_DIS_CFG      0x26\n+#define CPLD_CMD_ERASE        0x0E\n+#define CPLD_CMD_RESET_ADDR   0x46\n+#define CPLD_CMD_WRITE_PAGE   0x70\n+#define CPLD_CMD_SET_DONE     0x5E\n+#define CPLD_CMD_REFRESH      0x79\n+#define CPLD_PAGE_SIZE        16\n+\n+/* Status register bit positions (Lattice LCMXO3LF datasheet) */\n+#define CPLD_STATUS_DONE   BIT(8)\n+#define CPLD_STATUS_BUSY   BIT(12)\n+#define CPLD_STATUS_FAILED BIT(13)\n+\n+/*\n+ * adva_x1_i2c_xfer() - issue a single I2C transaction on the CPLD bus.\n+ *\n+ * All buffers are heap-allocated internally to guarantee DMA safety for\n+ * the Xilinx I2C controller.  Caller must hold bp-\u003ecpld_lock.\n+ */\n+static int adva_x1_i2c_xfer(struct ptp_ocp *bp,\n+\t\t\t    u8 addr, const void *wdata, u8 wlen,\n+\t\t\t    void *rdata, u8 rlen, bool nostart)\n+{\n+\tstruct i2c_adapter *adap;\n+\tstruct i2c_msg msgs[2];\n+\tu8 *wbuf = NULL, *rbuf = NULL;\n+\tint nmsgs = 0, ret;\n+\n+\tadap = i2c_get_adapter(READ_ONCE(bp-\u003ecpld_i2c_adap_nr));\n+\tif (!adap)\n+\t\treturn -ENODEV;\n+\n+\tif (wlen) {\n+\t\twbuf = kmemdup(wdata, wlen, GFP_KERNEL);\n+\t\tif (!wbuf) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto put;\n+\t\t}\n+\t\tmsgs[nmsgs++] = (struct i2c_msg){\n+\t\t\t.addr  = addr,\n+\t\t\t.flags = I2C_M_DMA_SAFE,\n+\t\t\t.len   = wlen,\n+\t\t\t.buf   = wbuf,\n+\t\t};\n+\t}\n+\tif (rlen) {\n+\t\trbuf = kzalloc(rlen, GFP_KERNEL);\n+\t\tif (!rbuf) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto put;\n+\t\t}\n+\t\tmsgs[nmsgs++] = (struct i2c_msg){\n+\t\t\t.addr  = addr,\n+\t\t\t.flags = I2C_M_RD | I2C_M_DMA_SAFE |\n+\t\t\t\t (nostart ? I2C_M_NOSTART : 0),\n+\t\t\t.len   = rlen,\n+\t\t\t.buf   = rbuf,\n+\t\t};\n+\t}\n+\n+\tret = i2c_transfer(adap, msgs, nmsgs);\n+\tif (ret == nmsgs) {\n+\t\tif (rdata \u0026\u0026 rlen)\n+\t\t\tmemcpy(rdata, rbuf, rlen);\n+\t\tret = 0;\n+\t} else {\n+\t\tret = (ret \u003c 0) ? ret : -EIO;\n+\t}\n+put:\n+\tkfree(wbuf);\n+\tkfree(rbuf);\n+\ti2c_put_adapter(adap);\n+\treturn ret;\n+}\n+\n+/* Acquire the shared I2C bus from the MicroBlaze firmware. */\n+static int adva_x1_mblaze_acquire(struct ptp_ocp *bp)\n+{\n+\tu32 val;\n+\tint i;\n+\n+\tif (!bp-\u003epps_select)\n+\t\treturn -ENODEV;\n+\n+\t/* Release any stale grant left by a previous crashed caller. */\n+\tiowrite32(0, \u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+\tval = ioread32(\u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+\tif (val != 0)\n+\t\treturn -EBUSY;\n+\n+\tiowrite32(MBLAZE_REQUEST, \u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+\tfor (i = 0; i \u003c MBLAZE_RETRIES; i++) {\n+\t\tusleep_range(MBLAZE_RETRY_US, MBLAZE_RETRY_US + 1000);\n+\t\tval = ioread32(\u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+\t\tif (val == MBLAZE_GRANTED)\n+\t\t\treturn 0;\n+\t}\n+\treturn -ETIMEDOUT;\n+}\n+\n+static void adva_x1_mblaze_release(struct ptp_ocp *bp)\n+{\n+\tif (bp-\u003epps_select)\n+\t\tiowrite32(MBLAZE_RELEASE, \u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+}\n+\n+static int adva_x1_mux_select(struct ptp_ocp *bp, int ch)\n+{\n+\tu8 val = (ch \u003e= 0) ? BIT(ch) : 0;\n+\n+\treturn adva_x1_i2c_xfer(bp, ADVA_MUX_ADDR, \u0026val, 1, NULL, 0, false);\n+}\n+\n+/* Send 1-byte ISC command + optional arguments. */\n+static int adva_x1_cpld_write(struct ptp_ocp *bp,\n+\t\t\t      u8 cmd, const u8 *args, u8 nargs)\n+{\n+\tu8 buf[1 + 64];\n+\n+\tif (nargs \u003e 64)\n+\t\treturn -EINVAL;\n+\tbuf[0] = cmd;\n+\tif (nargs)\n+\t\tmemcpy(\u0026buf[1], args, nargs);\n+\treturn adva_x1_i2c_xfer(bp, ADVA_CPLD_ADDR, buf, 1 + nargs,\n+\t\t\t\t NULL, 0, false);\n+}\n+\n+/*\n+ * Send a 4-byte command then read data back without an intermediate STOP\n+ * (Lattice combined write→repeated-START→read).\n+ */\n+static int adva_x1_cpld_cmd_read(struct ptp_ocp *bp,\n+\t\t\t\t u32 cmd_be, u8 *out, u8 out_len)\n+{\n+\t__be32 cmd = cpu_to_be32(cmd_be);\n+\n+\treturn adva_x1_i2c_xfer(bp, ADVA_CPLD_ADDR, \u0026cmd, 4, out, out_len, true);\n+}\n+\n+static int adva_x1_cpld_read_status(struct ptp_ocp *bp, u32 *status)\n+{\n+\tu8 buf[4];\n+\tint ret;\n+\n+\tret = adva_x1_cpld_cmd_read(bp, CPLD_CMD_READ_STATUS, buf, 4);\n+\tif (ret)\n+\t\treturn ret;\n+\t*status = get_unaligned_be32(buf);\n+\treturn 0;\n+}\n+\n+static int adva_x1_cpld_wait_ready(struct ptp_ocp *bp, unsigned int max_ms)\n+{\n+\tu32 status;\n+\tunsigned int elapsed = 0;\n+\n+\twhile (elapsed \u003c max_ms) {\n+\t\tif (adva_x1_cpld_read_status(bp, \u0026status))\n+\t\t\treturn -EIO;\n+\t\tif (status \u0026 CPLD_STATUS_FAILED)\n+\t\t\treturn -EIO;\n+\t\tif (!(status \u0026 CPLD_STATUS_BUSY))\n+\t\t\treturn 0;\n+\t\tusleep_range(100000, 101000);\n+\t\telapsed += 100;\n+\t}\n+\treturn -ETIMEDOUT;\n+}\n+\n+/*\n+ * cpld_device_id - show the Lattice device ID of the TAP CPLD.\n+ *\n+ * Returns the 32-bit ID as a hex string, e.g. \"0x612bc043\\n\".\n+ * Lattice LCMXO3LF-210 reports 0x612BC043.\n+ */\n+static ssize_t\n+cpld_device_id_show(struct device *dev, struct device_attribute *attr,\n+\t\t    char *buf)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(dev);\n+\tu8 data[4];\n+\tu32 id = 0;\n+\tint ret;\n+\n+\tmutex_lock(\u0026bp-\u003ecpld_lock);\n+\tret = adva_x1_mblaze_acquire(bp);\n+\tif (ret)\n+\t\tgoto out;\n+\tret = adva_x1_mux_select(bp, ADVA_MUX_CHANNEL);\n+\tif (ret)\n+\t\tgoto release;\n+\tret = adva_x1_cpld_cmd_read(bp, CPLD_CMD_READ_ID, data, 4);\n+\tif (!ret)\n+\t\tid = ((u32)data[0] \u003c\u003c 24) | ((u32)data[1] \u003c\u003c 16) |\n+\t\t     ((u32)data[2] \u003c\u003c  8) |  (u32)data[3];\n+\tadva_x1_mux_select(bp, -1);\n+release:\n+\tadva_x1_mblaze_release(bp);\n+out:\n+\tmutex_unlock(\u0026bp-\u003ecpld_lock);\n+\treturn ret ? ret : sysfs_emit(buf, \"0x%08x\\n\", id);\n+}\n+static DEVICE_ATTR_RO(cpld_device_id);\n+\n+/*\n+ * cpld_status - show the status register of the TAP CPLD.\n+ *\n+ * Returns a human-readable string: \"done=\u003c0|1\u003e busy=\u003c0|1\u003e failed=\u003c0|1\u003e\\n\"\n+ */\n+static ssize_t\n+cpld_status_show(struct device *dev, struct device_attribute *attr,\n+\t\t char *buf)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(dev);\n+\tu32 st = 0;\n+\tint ret;\n+\n+\tmutex_lock(\u0026bp-\u003ecpld_lock);\n+\tret = adva_x1_mblaze_acquire(bp);\n+\tif (ret)\n+\t\tgoto out;\n+\tret = adva_x1_mux_select(bp, ADVA_MUX_CHANNEL);\n+\tif (ret)\n+\t\tgoto release;\n+\tret = adva_x1_cpld_read_status(bp, \u0026st);\n+\tadva_x1_mux_select(bp, -1);\n+release:\n+\tadva_x1_mblaze_release(bp);\n+out:\n+\tmutex_unlock(\u0026bp-\u003ecpld_lock);\n+\treturn ret ? ret : sysfs_emit(buf, \"done=%u busy=%u failed=%u\\n\",\n+\t\t\t\t      !!(st \u0026 CPLD_STATUS_DONE),\n+\t\t\t\t      !!(st \u0026 CPLD_STATUS_BUSY),\n+\t\t\t\t      !!(st \u0026 CPLD_STATUS_FAILED));\n+}\n+static DEVICE_ATTR_RO(cpld_status);\n+\n+/*\n+ * adva_x1 CPLD firmware-upload callbacks.\n+ *\n+ * The kernel firmware-upload subsystem (CONFIG_FW_UPLOAD) exposes:\n+ *   /sys/class/firmware/adva-cpld/{data,loading,status,error,...}\n+ * Userspace writes the raw binary page data directly — no /lib/firmware/\n+ * staging file is needed.\n+ *\n+ * Callback sequence driven by the framework:\n+ *   prepare()      - validate size, acquire bus, enable config, erase flash\n+ *   write()        - program one 16-byte page per call\n+ *   poll_complete()- set DONE, REFRESH, wait for CPLD to reboot\n+ *   cancel()       - set flag; checked at the start of each callback\n+ *   cleanup()      - release bus resources (called on success or failure)\n+ */\n+static enum fw_upload_err\n+adva_cpld_prepare(struct fw_upload *fwl, const u8 *data, u32 size)\n+{\n+\tstruct ptp_ocp *bp = fwl-\u003edd_handle;\n+\tconst u8 en_args[2]  = { 0x08, 0x00 };\n+\tconst u8 era_args[3] = { 0x04, 0x00, 0x00 }; /* cfg sector only */\n+\tconst u8 zero3[3]    = { 0 };\n+\tconst u8 dis_args[2] = { 0x00, 0x00 };\n+\tenum fw_upload_err ret = FW_UPLOAD_ERR_NONE;\n+\n+\tif (!size || size % CPLD_PAGE_SIZE)\n+\t\treturn FW_UPLOAD_ERR_INVALID_SIZE;\n+\n+\tbp-\u003ecpld_cancel\t\t= false;\n+\tbp-\u003ecpld_in_config_mode\t= false;\n+\n+\tmutex_lock(\u0026bp-\u003ecpld_lock);\n+\n+\tif (adva_x1_mblaze_acquire(bp)) {\n+\t\tret = FW_UPLOAD_ERR_TIMEOUT;\n+\t\tgoto err_unlock;\n+\t}\n+\n+\tif (adva_x1_mux_select(bp, ADVA_MUX_CHANNEL)) {\n+\t\tret = FW_UPLOAD_ERR_HW_ERROR;\n+\t\tgoto err_release;\n+\t}\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_EN_CFG_TP, en_args, 2) ||\n+\t    adva_x1_cpld_wait_ready(bp, 5000)) {\n+\t\tret = FW_UPLOAD_ERR_HW_ERROR;\n+\t\tgoto err_deselect;\n+\t}\n+\tbp-\u003ecpld_in_config_mode = true;\n+\n+\tif (bp-\u003ecpld_cancel) {\n+\t\tret = FW_UPLOAD_ERR_CANCELED;\n+\t\tgoto err_deselect;\n+\t}\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_ERASE, era_args, 3) ||\n+\t    adva_x1_cpld_wait_ready(bp, 15000)) {\n+\t\tret = FW_UPLOAD_ERR_HW_ERROR;\n+\t\tgoto err_deselect;\n+\t}\n+\n+\tif (bp-\u003ecpld_cancel) {\n+\t\tret = FW_UPLOAD_ERR_CANCELED;\n+\t\tgoto err_deselect;\n+\t}\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_RESET_ADDR, zero3, 3)) {\n+\t\tret = FW_UPLOAD_ERR_HW_ERROR;\n+\t\tgoto err_deselect;\n+\t}\n+\n+\treturn FW_UPLOAD_ERR_NONE;\t/* cleanup() will unlock everything */\n+\n+err_deselect:\n+\tif (bp-\u003ecpld_in_config_mode) {\n+\t\tadva_x1_cpld_write(bp, CPLD_CMD_DIS_CFG, dis_args, 2);\n+\t\tbp-\u003ecpld_in_config_mode = false;\n+\t}\n+\tadva_x1_mux_select(bp, -1);\n+err_release:\n+\tadva_x1_mblaze_release(bp);\n+err_unlock:\n+\tmutex_unlock(\u0026bp-\u003ecpld_lock);\n+\treturn ret;\n+}\n+\n+static enum fw_upload_err\n+adva_cpld_write(struct fw_upload *fwl, const u8 *data,\n+\t\tu32 offset, u32 size, u32 *written)\n+{\n+\tstruct ptp_ocp *bp = fwl-\u003edd_handle;\n+\tu8 page_args[3 + CPLD_PAGE_SIZE];\n+\n+\tif (bp-\u003ecpld_cancel)\n+\t\treturn FW_UPLOAD_ERR_CANCELED;\n+\n+\tif (size \u003c CPLD_PAGE_SIZE)\n+\t\treturn FW_UPLOAD_ERR_INVALID_SIZE;\n+\n+\tpage_args[0] = 0x00;\n+\tpage_args[1] = 0x00;\n+\tpage_args[2] = 0x01;\n+\tmemcpy(\u0026page_args[3], data + offset, CPLD_PAGE_SIZE);\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_WRITE_PAGE,\n+\t\t\t       page_args, 3 + CPLD_PAGE_SIZE) ||\n+\t    adva_x1_cpld_wait_ready(bp, 100))\n+\t\treturn FW_UPLOAD_ERR_HW_ERROR;\n+\n+\t*written = CPLD_PAGE_SIZE;\n+\treturn FW_UPLOAD_ERR_NONE;\n+}\n+\n+static enum fw_upload_err\n+adva_cpld_poll_complete(struct fw_upload *fwl)\n+{\n+\tstruct ptp_ocp *bp = fwl-\u003edd_handle;\n+\tconst u8 zero3[3]    = { 0 };\n+\tconst u8 ref_args[2] = { 0x00, 0x00 };\n+\tu32 st;\n+\n+\tif (bp-\u003ecpld_cancel)\n+\t\treturn FW_UPLOAD_ERR_CANCELED;\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_SET_DONE, zero3, 3) ||\n+\t    adva_x1_cpld_wait_ready(bp, 1000))\n+\t\treturn FW_UPLOAD_ERR_HW_ERROR;\n+\n+\tif (adva_x1_cpld_read_status(bp, \u0026st) || !(st \u0026 CPLD_STATUS_DONE))\n+\t\treturn FW_UPLOAD_ERR_HW_ERROR;\n+\n+\tif (adva_x1_cpld_write(bp, CPLD_CMD_REFRESH, ref_args, 2))\n+\t\treturn FW_UPLOAD_ERR_HW_ERROR;\n+\n+\t/* CPLD reboots after REFRESH; re-select mux once it comes back up */\n+\tmsleep(1500);\n+\tadva_x1_mux_select(bp, ADVA_MUX_CHANNEL);\n+\tif (adva_x1_cpld_wait_ready(bp, 3000))\n+\t\treturn FW_UPLOAD_ERR_TIMEOUT;\n+\n+\tbp-\u003ecpld_in_config_mode = false;\n+\treturn FW_UPLOAD_ERR_NONE;\n+}\n+\n+static void\n+adva_cpld_cancel(struct fw_upload *fwl)\n+{\n+\tstruct ptp_ocp *bp = fwl-\u003edd_handle;\n+\n+\tbp-\u003ecpld_cancel = true;\n+}\n+\n+static void\n+adva_cpld_cleanup(struct fw_upload *fwl)\n+{\n+\tstruct ptp_ocp *bp = fwl-\u003edd_handle;\n+\tconst u8 dis_args[2] = { 0x00, 0x00 };\n+\n+\tif (bp-\u003ecpld_in_config_mode) {\n+\t\tadva_x1_cpld_write(bp, CPLD_CMD_DIS_CFG, dis_args, 2);\n+\t\tbp-\u003ecpld_in_config_mode = false;\n+\t}\n+\tadva_x1_mux_select(bp, -1);\n+\tadva_x1_mblaze_release(bp);\n+\tmutex_unlock(\u0026bp-\u003ecpld_lock);\n+}\n+\n+static const struct fw_upload_ops adva_cpld_upload_ops = {\n+\t.prepare\t = adva_cpld_prepare,\n+\t.write\t\t = adva_cpld_write,\n+\t.poll_complete\t = adva_cpld_poll_complete,\n+\t.cancel\t\t = adva_cpld_cancel,\n+\t.cleanup\t = adva_cpld_cleanup,\n+};\n+\n static struct attribute *adva_timecard_attrs[] = {\n \t\u0026dev_attr_serialnum.attr,\n \t\u0026dev_attr_gnss_sync.attr,\n@@ -4272,6 +4739,8 @@ static struct attribute *adva_timecard_x1_attrs[] = {\n \t\u0026dev_attr_ts_window_adjust.attr,\n \t\u0026dev_attr_utc_tai_offset.attr,\n \t\u0026dev_attr_tod_correction.attr,\n+\t\u0026dev_attr_cpld_device_id.attr,\n+\t\u0026dev_attr_cpld_status.attr,\n \tNULL,\n };\n \n@@ -4902,6 +5371,11 @@ ptp_ocp_detach(struct ptp_ocp *bp)\n \t\tclk_hw_unregister_fixed_rate(bp-\u003ei2c_clk);\n \tif (bp-\u003en_irqs)\n \t\tpci_free_irq_vectors(bp-\u003epdev);\n+\tif (bp-\u003ecpld_fw_upload) {\n+\t\tfirmware_upload_unregister(bp-\u003ecpld_fw_upload);\n+\t\tbp-\u003ecpld_fw_upload = NULL;\n+\t}\n+\tmutex_destroy(\u0026bp-\u003ecpld_lock);\n \tdevice_unregister(\u0026bp-\u003edev);\n }\n \n@@ -5078,6 +5552,17 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \tif (err)\n \t\tgoto out_disable;\n \n+\t/* Must be before the first error path that calls ptp_ocp_detach(),\n+\t * so mutex_destroy() always runs on an initialised mutex.\n+\t * Must also be before ptp_ocp_register_resources(): the I2C bus\n+\t * notifier (ptp_ocp_i2c_notifier_call) fires when the adapter\n+\t * registers and stores the adapter number in cpld_i2c_adap_nr; the\n+\t * -1 sentinel below must already be written so that a notifier\n+\t * firing during registration is never overwritten by this init.\n+\t */\n+\tmutex_init(\u0026bp-\u003ecpld_lock);\n+\tbp-\u003ecpld_i2c_adap_nr = -1;\n+\n \tINIT_DELAYED_WORK(\u0026bp-\u003esync_work, ptp_ocp_sync_work);\n \n \t/* compat mode.\n@@ -5217,11 +5702,16 @@ ptp_ocp_i2c_notifier_call(struct notifier_block *nb,\n \n found:\n \tbp = dev_get_drvdata(dev);\n-\tif (add)\n+\tif (add) {\n \t\tptp_ocp_symlink(bp, child, \"i2c\");\n-\telse\n+\t\t/* Cache adapter nr; used by cpld_device_id/cpld_status/cpld_program\n+\t\t * for reference-counted unbind-safe adapter access.\n+\t\t */\n+\t\tWRITE_ONCE(bp-\u003ecpld_i2c_adap_nr, i2c_verify_adapter(child)-\u003enr);\n+\t} else {\n+\t\tWRITE_ONCE(bp-\u003ecpld_i2c_adap_nr, -1); /* invalidate before free */\n \t\tsysfs_remove_link(\u0026bp-\u003edev.kobj, \"i2c\");\n-\n+\t}\n \treturn 0;\n }\n \n"
}

2/1 2026/08/03 19:41 agent patch-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds CPLD firmware upload and sysfs attributes for the ADVA x1 OCP Timecard, which is a physical PCIe device. The new code heavily relies on hardware-specific interactions (e.g., polling MMIO registers for MicroBlaze firmware grants, I2C communication with a PCA9548 mux and Lattice CPLD) that are not emulated in standard QEMU environments. Consequently, the core logic is unreachable during fuzzing without the physical hardware.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit b1c53476f5ea039ac1a344d1b990df9a4f95766a
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Aug 3 19:41:08 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/ABI/testing/sysfs-timecard b/Documentation/ABI/testing/sysfs-timecard
index 3ae41b7634ac9..f7c9955acb0a9 100644
--- a/Documentation/ABI/testing/sysfs-timecard
+++ b/Documentation/ABI/testing/sysfs-timecard
@@ -11,6 +11,40 @@ Contact:	Jonathan Lemon <jonathan.lemon@gmail.com>
 Description:	This directory contains the attributes of the Nth timecard
 		registered.
 
+What:		/sys/class/timecard/ocpN/cpld_device_id
+Date:		July 2026
+Contact:	Sagi Maimon <maimon.sagi@gmail.com>
+Description:	(RO) The 32-bit Lattice device ID of the TAP CPLD, reported as
+		a hex string, e.g. "0xe12bc043".
+
+		Only present on ADVA x1 TAP boards (PCI ID 0xad5a:0x0410).
+		The Lattice LCMXO3LF-210 reports 0xe12bc043.
+
+		The driver acquires the MicroBlaze I2C bus internally before
+		issuing the READ_IDCODE command; no bus arbitration is required
+		from userspace.
+
+What:		/sys/class/timecard/ocpN/cpld_status
+Date:		July 2026
+Contact:	Sagi Maimon <maimon.sagi@gmail.com>
+Description:	(RO) The status register of the TAP CPLD, in human-readable
+		form:
+
+		  done=<0|1> busy=<0|1> failed=<0|1>
+
+		Only present on ADVA x1 TAP boards (PCI ID 0xad5a:0x0410).
+
+		done=1 indicates the configuration flash was successfully
+		programmed and is active.  busy=1 means an internal operation
+		is in progress.  failed=1 means the last ISC operation failed.
+
+		The driver acquires the MicroBlaze I2C bus internally; no bus
+		arbitration is required from userspace.
+
+		To program new CPLD firmware use the standard kernel
+		firmware-upload interface registered at:
+		/sys/class/firmware/adva-cpld/
+
 What:		/sys/class/timecard/ocpN/available_clock_sources
 Date:		September 2021
 Contact:	Jonathan Lemon <jonathan.lemon@gmail.com>
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 35e911f1ad78c..db8ab161d4f0f 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -24,6 +24,11 @@
 #include <linux/nvmem-consumer.h>
 #include <linux/crc16.h>
 #include <linux/dpll.h>
+#include <linux/unaligned.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
 
 #define PCI_DEVICE_ID_META_TIMECARD		0x0400
 
@@ -85,6 +90,7 @@ struct ptp_ocp_adva_info {
 	u8				signals_nr;
 	u8				freq_in_nr;
 	const struct ocp_attr_group	*attr_groups;
+	bool				has_cpld; /* x1: supports CPLD firmware upload */
 };
 
 #define OCP_CTRL_ENABLE		BIT(0)
@@ -163,7 +169,8 @@ struct gpio_reg {
 	u32	gpio1;
 	u32	__pad0;
 	u32	gpio2;
-	u32	__pad1;
+	/* adva_x1: I2C bus ownership register; reserved on other variants */
+	u32	i2c_bus_ctrl;
 };
 
 struct irig_master_reg {
@@ -416,6 +423,12 @@ struct ptp_ocp {
 	dpll_tracker tracker;
 	int signals_nr;
 	int freq_in_nr;
+	/* adva_x1 CPLD I2C (internal use only) */
+	struct mutex		cpld_lock;            /* serialises CPLD operations */
+	int			cpld_i2c_adap_nr;     /* I2C adapter nr; -1 if absent */
+	struct fw_upload	*cpld_fw_upload;      /* firmware upload handle; NULL if absent */
+	bool			cpld_cancel;          /* cancellation requested */
+	bool			cpld_in_config_mode;  /* EN_CFG_TP issued but not yet REFRESH'd */
 };
 
 #define OCP_REQ_TIMESTAMP	BIT(0)
@@ -449,6 +462,8 @@ static int ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
 
 static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
 
+static const struct fw_upload_ops adva_cpld_upload_ops;
+
 static const struct ocp_sma_op ocp_adva_sma_op;
 static const struct ocp_sma_op ocp_adva_x1_sma_op;
 
@@ -1273,6 +1288,7 @@ static struct ocp_resource ocp_adva_x1_resource[] = {
 			.signals_nr   = 4,
 			.freq_in_nr   = 4,
 			.attr_groups  = adva_timecard_x1_groups,
+			.has_cpld     = true,
 		},
 	},
 	{ }
@@ -3197,6 +3213,20 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
 		return err;
 	ptp_ocp_sma_init(bp);
 
+	if (info->has_cpld) {
+		struct fw_upload *fwl;
+
+		fwl = firmware_upload_register(THIS_MODULE, &bp->pdev->dev,
+					       "adva-cpld",
+					       &adva_cpld_upload_ops, bp);
+		if (IS_ERR(fwl))
+			dev_warn(&bp->pdev->dev,
+				 "CPLD firmware upload unavailable: %pe\n",
+				 fwl);
+		else
+			bp->cpld_fw_upload = fwl;
+	}
+
 	return ptp_ocp_init_clock(bp, &info->servo);
 }
 
@@ -4224,6 +4254,443 @@ static const struct ocp_attr_group art_timecard_groups[] = {
 	{ },
 };
 
+/*
+ * Internal helpers for the adva_x1 TAP CPLD (Lattice LCMXO3LF-210).
+ *
+ * The CPLD sits at I2C address 0x40 behind a PCA9548 mux (0x74) on
+ * channel 0.  The I2C bus is shared with the MicroBlaze firmware;
+ * cpld_lock + mblaze acquire/release provide mutual exclusion for the
+ * full duration of any CPLD operation.  No raw I2C access is exposed
+ * to userspace; only the high-level attributes below are.
+ */
+
+#define ADVA_MUX_ADDR     0x74
+#define ADVA_CPLD_ADDR    0x40
+#define ADVA_MUX_CHANNEL  0
+
+#define MBLAZE_REQUEST    0x0000aaaaU
+#define MBLAZE_GRANTED    0x5555aaaaU
+#define MBLAZE_RELEASE    0x55550000U
+#define MBLAZE_RETRIES    200
+#define MBLAZE_RETRY_US   10000
+
+/* Lattice LCMXO3LF ISC command codes */
+#define CPLD_CMD_READ_ID      0xE0000000UL
+#define CPLD_CMD_READ_STATUS  0x3C000000UL
+#define CPLD_CMD_EN_CFG_TP    0x74   /* enable config, transparent mode */
+#define CPLD_CMD_DIS_CFG      0x26
+#define CPLD_CMD_ERASE        0x0E
+#define CPLD_CMD_RESET_ADDR   0x46
+#define CPLD_CMD_WRITE_PAGE   0x70
+#define CPLD_CMD_SET_DONE     0x5E
+#define CPLD_CMD_REFRESH      0x79
+#define CPLD_PAGE_SIZE        16
+
+/* Status register bit positions (Lattice LCMXO3LF datasheet) */
+#define CPLD_STATUS_DONE   BIT(8)
+#define CPLD_STATUS_BUSY   BIT(12)
+#define CPLD_STATUS_FAILED BIT(13)
+
+/*
+ * adva_x1_i2c_xfer() - issue a single I2C transaction on the CPLD bus.
+ *
+ * All buffers are heap-allocated internally to guarantee DMA safety for
+ * the Xilinx I2C controller.  Caller must hold bp->cpld_lock.
+ */
+static int adva_x1_i2c_xfer(struct ptp_ocp *bp,
+			    u8 addr, const void *wdata, u8 wlen,
+			    void *rdata, u8 rlen, bool nostart)
+{
+	struct i2c_adapter *adap;
+	struct i2c_msg msgs[2];
+	u8 *wbuf = NULL, *rbuf = NULL;
+	int nmsgs = 0, ret;
+
+	adap = i2c_get_adapter(READ_ONCE(bp->cpld_i2c_adap_nr));
+	if (!adap)
+		return -ENODEV;
+
+	if (wlen) {
+		wbuf = kmemdup(wdata, wlen, GFP_KERNEL);
+		if (!wbuf) {
+			ret = -ENOMEM;
+			goto put;
+		}
+		msgs[nmsgs++] = (struct i2c_msg){
+			.addr  = addr,
+			.flags = I2C_M_DMA_SAFE,
+			.len   = wlen,
+			.buf   = wbuf,
+		};
+	}
+	if (rlen) {
+		rbuf = kzalloc(rlen, GFP_KERNEL);
+		if (!rbuf) {
+			ret = -ENOMEM;
+			goto put;
+		}
+		msgs[nmsgs++] = (struct i2c_msg){
+			.addr  = addr,
+			.flags = I2C_M_RD | I2C_M_DMA_SAFE |
+				 (nostart ? I2C_M_NOSTART : 0),
+			.len   = rlen,
+			.buf   = rbuf,
+		};
+	}
+
+	ret = i2c_transfer(adap, msgs, nmsgs);
+	if (ret == nmsgs) {
+		if (rdata && rlen)
+			memcpy(rdata, rbuf, rlen);
+		ret = 0;
+	} else {
+		ret = (ret < 0) ? ret : -EIO;
+	}
+put:
+	kfree(wbuf);
+	kfree(rbuf);
+	i2c_put_adapter(adap);
+	return ret;
+}
+
+/* Acquire the shared I2C bus from the MicroBlaze firmware. */
+static int adva_x1_mblaze_acquire(struct ptp_ocp *bp)
+{
+	u32 val;
+	int i;
+
+	if (!bp->pps_select)
+		return -ENODEV;
+
+	/* Release any stale grant left by a previous crashed caller. */
+	iowrite32(0, &bp->pps_select->i2c_bus_ctrl);
+	val = ioread32(&bp->pps_select->i2c_bus_ctrl);
+	if (val != 0)
+		return -EBUSY;
+
+	iowrite32(MBLAZE_REQUEST, &bp->pps_select->i2c_bus_ctrl);
+	for (i = 0; i < MBLAZE_RETRIES; i++) {
+		usleep_range(MBLAZE_RETRY_US, MBLAZE_RETRY_US + 1000);
+		val = ioread32(&bp->pps_select->i2c_bus_ctrl);
+		if (val == MBLAZE_GRANTED)
+			return 0;
+	}
+	return -ETIMEDOUT;
+}
+
+static void adva_x1_mblaze_release(struct ptp_ocp *bp)
+{
+	if (bp->pps_select)
+		iowrite32(MBLAZE_RELEASE, &bp->pps_select->i2c_bus_ctrl);
+}
+
+static int adva_x1_mux_select(struct ptp_ocp *bp, int ch)
+{
+	u8 val = (ch >= 0) ? BIT(ch) : 0;
+
+	return adva_x1_i2c_xfer(bp, ADVA_MUX_ADDR, &val, 1, NULL, 0, false);
+}
+
+/* Send 1-byte ISC command + optional arguments. */
+static int adva_x1_cpld_write(struct ptp_ocp *bp,
+			      u8 cmd, const u8 *args, u8 nargs)
+{
+	u8 buf[1 + 64];
+
+	if (nargs > 64)
+		return -EINVAL;
+	buf[0] = cmd;
+	if (nargs)
+		memcpy(&buf[1], args, nargs);
+	return adva_x1_i2c_xfer(bp, ADVA_CPLD_ADDR, buf, 1 + nargs,
+				 NULL, 0, false);
+}
+
+/*
+ * Send a 4-byte command then read data back without an intermediate STOP
+ * (Lattice combined write→repeated-START→read).
+ */
+static int adva_x1_cpld_cmd_read(struct ptp_ocp *bp,
+				 u32 cmd_be, u8 *out, u8 out_len)
+{
+	__be32 cmd = cpu_to_be32(cmd_be);
+
+	return adva_x1_i2c_xfer(bp, ADVA_CPLD_ADDR, &cmd, 4, out, out_len, true);
+}
+
+static int adva_x1_cpld_read_status(struct ptp_ocp *bp, u32 *status)
+{
+	u8 buf[4];
+	int ret;
+
+	ret = adva_x1_cpld_cmd_read(bp, CPLD_CMD_READ_STATUS, buf, 4);
+	if (ret)
+		return ret;
+	*status = get_unaligned_be32(buf);
+	return 0;
+}
+
+static int adva_x1_cpld_wait_ready(struct ptp_ocp *bp, unsigned int max_ms)
+{
+	u32 status;
+	unsigned int elapsed = 0;
+
+	while (elapsed < max_ms) {
+		if (adva_x1_cpld_read_status(bp, &status))
+			return -EIO;
+		if (status & CPLD_STATUS_FAILED)
+			return -EIO;
+		if (!(status & CPLD_STATUS_BUSY))
+			return 0;
+		usleep_range(100000, 101000);
+		elapsed += 100;
+	}
+	return -ETIMEDOUT;
+}
+
+/*
+ * cpld_device_id - show the Lattice device ID of the TAP CPLD.
+ *
+ * Returns the 32-bit ID as a hex string, e.g. "0x612bc043\n".
+ * Lattice LCMXO3LF-210 reports 0x612BC043.
+ */
+static ssize_t
+cpld_device_id_show(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct ptp_ocp *bp = dev_get_drvdata(dev);
+	u8 data[4];
+	u32 id = 0;
+	int ret;
+
+	mutex_lock(&bp->cpld_lock);
+	ret = adva_x1_mblaze_acquire(bp);
+	if (ret)
+		goto out;
+	ret = adva_x1_mux_select(bp, ADVA_MUX_CHANNEL);
+	if (ret)
+		goto release;
+	ret = adva_x1_cpld_cmd_read(bp, CPLD_CMD_READ_ID, data, 4);
+	if (!ret)
+		id = ((u32)data[0] << 24) | ((u32)data[1] << 16) |
+		     ((u32)data[2] <<  8) |  (u32)data[3];
+	adva_x1_mux_select(bp, -1);
+release:
+	adva_x1_mblaze_release(bp);
+out:
+	mutex_unlock(&bp->cpld_lock);
+	return ret ? ret : sysfs_emit(buf, "0x%08x\n", id);
+}
+static DEVICE_ATTR_RO(cpld_device_id);
+
+/*
+ * cpld_status - show the status register of the TAP CPLD.
+ *
+ * Returns a human-readable string: "done=<0|1> busy=<0|1> failed=<0|1>\n"
+ */
+static ssize_t
+cpld_status_show(struct device *dev, struct device_attribute *attr,
+		 char *buf)
+{
+	struct ptp_ocp *bp = dev_get_drvdata(dev);
+	u32 st = 0;
+	int ret;
+
+	mutex_lock(&bp->cpld_lock);
+	ret = adva_x1_mblaze_acquire(bp);
+	if (ret)
+		goto out;
+	ret = adva_x1_mux_select(bp, ADVA_MUX_CHANNEL);
+	if (ret)
+		goto release;
+	ret = adva_x1_cpld_read_status(bp, &st);
+	adva_x1_mux_select(bp, -1);
+release:
+	adva_x1_mblaze_release(bp);
+out:
+	mutex_unlock(&bp->cpld_lock);
+	return ret ? ret : sysfs_emit(buf, "done=%u busy=%u failed=%u\n",
+				      !!(st & CPLD_STATUS_DONE),
+				      !!(st & CPLD_STATUS_BUSY),
+				      !!(st & CPLD_STATUS_FAILED));
+}
+static DEVICE_ATTR_RO(cpld_status);
+
+/*
+ * adva_x1 CPLD firmware-upload callbacks.
+ *
+ * The kernel firmware-upload subsystem (CONFIG_FW_UPLOAD) exposes:
+ *   /sys/class/firmware/adva-cpld/{data,loading,status,error,...}
+ * Userspace writes the raw binary page data directly — no /lib/firmware/
+ * staging file is needed.
+ *
+ * Callback sequence driven by the framework:
+ *   prepare()      - validate size, acquire bus, enable config, erase flash
+ *   write()        - program one 16-byte page per call
+ *   poll_complete()- set DONE, REFRESH, wait for CPLD to reboot
+ *   cancel()       - set flag; checked at the start of each callback
+ *   cleanup()      - release bus resources (called on success or failure)
+ */
+static enum fw_upload_err
+adva_cpld_prepare(struct fw_upload *fwl, const u8 *data, u32 size)
+{
+	struct ptp_ocp *bp = fwl->dd_handle;
+	const u8 en_args[2]  = { 0x08, 0x00 };
+	const u8 era_args[3] = { 0x04, 0x00, 0x00 }; /* cfg sector only */
+	const u8 zero3[3]    = { 0 };
+	const u8 dis_args[2] = { 0x00, 0x00 };
+	enum fw_upload_err ret = FW_UPLOAD_ERR_NONE;
+
+	if (!size || size % CPLD_PAGE_SIZE)
+		return FW_UPLOAD_ERR_INVALID_SIZE;
+
+	bp->cpld_cancel		= false;
+	bp->cpld_in_config_mode	= false;
+
+	mutex_lock(&bp->cpld_lock);
+
+	if (adva_x1_mblaze_acquire(bp)) {
+		ret = FW_UPLOAD_ERR_TIMEOUT;
+		goto err_unlock;
+	}
+
+	if (adva_x1_mux_select(bp, ADVA_MUX_CHANNEL)) {
+		ret = FW_UPLOAD_ERR_HW_ERROR;
+		goto err_release;
+	}
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_EN_CFG_TP, en_args, 2) ||
+	    adva_x1_cpld_wait_ready(bp, 5000)) {
+		ret = FW_UPLOAD_ERR_HW_ERROR;
+		goto err_deselect;
+	}
+	bp->cpld_in_config_mode = true;
+
+	if (bp->cpld_cancel) {
+		ret = FW_UPLOAD_ERR_CANCELED;
+		goto err_deselect;
+	}
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_ERASE, era_args, 3) ||
+	    adva_x1_cpld_wait_ready(bp, 15000)) {
+		ret = FW_UPLOAD_ERR_HW_ERROR;
+		goto err_deselect;
+	}
+
+	if (bp->cpld_cancel) {
+		ret = FW_UPLOAD_ERR_CANCELED;
+		goto err_deselect;
+	}
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_RESET_ADDR, zero3, 3)) {
+		ret = FW_UPLOAD_ERR_HW_ERROR;
+		goto err_deselect;
+	}
+
+	return FW_UPLOAD_ERR_NONE;	/* cleanup() will unlock everything */
+
+err_deselect:
+	if (bp->cpld_in_config_mode) {
+		adva_x1_cpld_write(bp, CPLD_CMD_DIS_CFG, dis_args, 2);
+		bp->cpld_in_config_mode = false;
+	}
+	adva_x1_mux_select(bp, -1);
+err_release:
+	adva_x1_mblaze_release(bp);
+err_unlock:
+	mutex_unlock(&bp->cpld_lock);
+	return ret;
+}
+
+static enum fw_upload_err
+adva_cpld_write(struct fw_upload *fwl, const u8 *data,
+		u32 offset, u32 size, u32 *written)
+{
+	struct ptp_ocp *bp = fwl->dd_handle;
+	u8 page_args[3 + CPLD_PAGE_SIZE];
+
+	if (bp->cpld_cancel)
+		return FW_UPLOAD_ERR_CANCELED;
+
+	if (size < CPLD_PAGE_SIZE)
+		return FW_UPLOAD_ERR_INVALID_SIZE;
+
+	page_args[0] = 0x00;
+	page_args[1] = 0x00;
+	page_args[2] = 0x01;
+	memcpy(&page_args[3], data + offset, CPLD_PAGE_SIZE);
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_WRITE_PAGE,
+			       page_args, 3 + CPLD_PAGE_SIZE) ||
+	    adva_x1_cpld_wait_ready(bp, 100))
+		return FW_UPLOAD_ERR_HW_ERROR;
+
+	*written = CPLD_PAGE_SIZE;
+	return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err
+adva_cpld_poll_complete(struct fw_upload *fwl)
+{
+	struct ptp_ocp *bp = fwl->dd_handle;
+	const u8 zero3[3]    = { 0 };
+	const u8 ref_args[2] = { 0x00, 0x00 };
+	u32 st;
+
+	if (bp->cpld_cancel)
+		return FW_UPLOAD_ERR_CANCELED;
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_SET_DONE, zero3, 3) ||
+	    adva_x1_cpld_wait_ready(bp, 1000))
+		return FW_UPLOAD_ERR_HW_ERROR;
+
+	if (adva_x1_cpld_read_status(bp, &st) || !(st & CPLD_STATUS_DONE))
+		return FW_UPLOAD_ERR_HW_ERROR;
+
+	if (adva_x1_cpld_write(bp, CPLD_CMD_REFRESH, ref_args, 2))
+		return FW_UPLOAD_ERR_HW_ERROR;
+
+	/* CPLD reboots after REFRESH; re-select mux once it comes back up */
+	msleep(1500);
+	adva_x1_mux_select(bp, ADVA_MUX_CHANNEL);
+	if (adva_x1_cpld_wait_ready(bp, 3000))
+		return FW_UPLOAD_ERR_TIMEOUT;
+
+	bp->cpld_in_config_mode = false;
+	return FW_UPLOAD_ERR_NONE;
+}
+
+static void
+adva_cpld_cancel(struct fw_upload *fwl)
+{
+	struct ptp_ocp *bp = fwl->dd_handle;
+
+	bp->cpld_cancel = true;
+}
+
+static void
+adva_cpld_cleanup(struct fw_upload *fwl)
+{
+	struct ptp_ocp *bp = fwl->dd_handle;
+	const u8 dis_args[2] = { 0x00, 0x00 };
+
+	if (bp->cpld_in_config_mode) {
+		adva_x1_cpld_write(bp, CPLD_CMD_DIS_CFG, dis_args, 2);
+		bp->cpld_in_config_mode = false;
+	}
+	adva_x1_mux_select(bp, -1);
+	adva_x1_mblaze_release(bp);
+	mutex_unlock(&bp->cpld_lock);
+}
+
+static const struct fw_upload_ops adva_cpld_upload_ops = {
+	.prepare	 = adva_cpld_prepare,
+	.write		 = adva_cpld_write,
+	.poll_complete	 = adva_cpld_poll_complete,
+	.cancel		 = adva_cpld_cancel,
+	.cleanup	 = adva_cpld_cleanup,
+};
+
 static struct attribute *adva_timecard_attrs[] = {
 	&dev_attr_serialnum.attr,
 	&dev_attr_gnss_sync.attr,
@@ -4272,6 +4739,8 @@ static struct attribute *adva_timecard_x1_attrs[] = {
 	&dev_attr_ts_window_adjust.attr,
 	&dev_attr_utc_tai_offset.attr,
 	&dev_attr_tod_correction.attr,
+	&dev_attr_cpld_device_id.attr,
+	&dev_attr_cpld_status.attr,
 	NULL,
 };
 
@@ -4902,6 +5371,11 @@ ptp_ocp_detach(struct ptp_ocp *bp)
 		clk_hw_unregister_fixed_rate(bp->i2c_clk);
 	if (bp->n_irqs)
 		pci_free_irq_vectors(bp->pdev);
+	if (bp->cpld_fw_upload) {
+		firmware_upload_unregister(bp->cpld_fw_upload);
+		bp->cpld_fw_upload = NULL;
+	}
+	mutex_destroy(&bp->cpld_lock);
 	device_unregister(&bp->dev);
 }
 
@@ -5078,6 +5552,17 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (err)
 		goto out_disable;
 
+	/* Must be before the first error path that calls ptp_ocp_detach(),
+	 * so mutex_destroy() always runs on an initialised mutex.
+	 * Must also be before ptp_ocp_register_resources(): the I2C bus
+	 * notifier (ptp_ocp_i2c_notifier_call) fires when the adapter
+	 * registers and stores the adapter number in cpld_i2c_adap_nr; the
+	 * -1 sentinel below must already be written so that a notifier
+	 * firing during registration is never overwritten by this init.
+	 */
+	mutex_init(&bp->cpld_lock);
+	bp->cpld_i2c_adap_nr = -1;
+
 	INIT_DELAYED_WORK(&bp->sync_work, ptp_ocp_sync_work);
 
 	/* compat mode.
@@ -5217,11 +5702,16 @@ ptp_ocp_i2c_notifier_call(struct notifier_block *nb,
 
 found:
 	bp = dev_get_drvdata(dev);
-	if (add)
+	if (add) {
 		ptp_ocp_symlink(bp, child, "i2c");
-	else
+		/* Cache adapter nr; used by cpld_device_id/cpld_status/cpld_program
+		 * for reference-counted unbind-safe adapter access.
+		 */
+		WRITE_ONCE(bp->cpld_i2c_adap_nr, i2c_verify_adapter(child)->nr);
+	} else {
+		WRITE_ONCE(bp->cpld_i2c_adap_nr, -1); /* invalidate before free */
 		sysfs_remove_link(&bp->dev.kobj, "i2c");
-
+	}
 	return 0;
 }
 

3/2 2026/08/03 19:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10007
							output: 30
							thoughts: 439
						

Thoughts:
**Analyzing the `ptp_ocp` Driver Patch**

Okay, so I've got this patch that touches the `ptp_ocp` driver, specifically `drivers/ptp/ptp_ocp.c`. It's adding CPLD firmware upload support, which is interesting. It mentions the `firmware_upload` framework and also introduces `cpld_device_id` and `cpld_status` sysfs attributes. My immediate thought is, "Is this reachable and testable?".

The driver is a PCI driver, and the device ID, according to the documentation, is `0xad5a:0x0410`. Let me quickly double-check that in the code itself. Okay, the code does check for `info->has_cpld`, and it’s set to `true` specifically for the `ocp_adva_x1_resource`. So this is definitely a PCI device driver.

The million-dollar question: Can this be fuzzed? Given that it's PCI, Syzkaller should be able to fuzz it using its pseudo-PCI subsystem, or vhci, or some other PCI fuzzing support. Syzkaller has been making strides in this area. But wait... this prompt is a bit ominous, it mentions "vendor-specific PCIe switch, SmartNIC, or GPU drivers... that require physical PCIe hardware cards not emulated in standard QEMU". Is this a case? Is `ptp_ocp` vendor-specific?

It's the "Open Compute Project time card driver"... that doesn't sound specifically vendor-locked. I should check how it's handled. The real question is: is it fuzzed already, or can it be? Hold on, the commit author is listed as `syz-cluster <triage@syzkaller.com>`. Now that's interesting! Syzkaller is either finding something, or this is a test patch. Wait, the commit message says "syz-cluster: applied patch under review", which is great, meaning Syzkaller had a role in this, which is good news for our goals.

Okay, let me confirm if `ptp_ocp` is a standard driver or needs physical hardware. Because this is the crucial point for my work. It's a PCI driver... so let's do a quick grep search for `ptp_ocp` in the kernel to see the larger context.



4/2 2026/08/03 19:41 tool grepper
0m Args:
{
  "Expression": "ptp_ocp",
  "PathPrefix": "drivers/ptp/"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 2087 lines.\nUse more precise expression if possible.\n\ndrivers/ptp/Makefile=20=obj-$(CONFIG_PTP_1588_CLOCK_VMW)\t+= ptp_vmw.o\ndrivers/ptp/Makefile:21:obj-$(CONFIG_PTP_1588_CLOCK_OCP)\t+= ptp_ocp.o\ndrivers/ptp/Makefile-22-obj-$(CONFIG_PTP_DFL_TOD)\t\t+= ptp_dfl_tod.o\n--\ndrivers/ptp/ptp_ocp.c=49=struct ocp_reg {\n--\ndrivers/ptp/ptp_ocp.c-73-\ndrivers/ptp/ptp_ocp.c:74:struct ptp_ocp_servo_conf {\ndrivers/ptp/ptp_ocp.c-75-\tu32\tservo_offset_p;\n--\ndrivers/ptp/ptp_ocp.c-82- * Combined servo + board-variant parameters for ADVA boards.\ndrivers/ptp/ptp_ocp.c:83: * Embedded in the resource table .extra so a single ptp_ocp_adva_board_init()\ndrivers/ptp/ptp_ocp.c-84- * can handle both ADVA and ADVA-X1 without per-variant init functions.\ndrivers/ptp/ptp_ocp.c-85- */\ndrivers/ptp/ptp_ocp.c:86:struct ptp_ocp_adva_info {\ndrivers/ptp/ptp_ocp.c:87:\tstruct ptp_ocp_servo_conf\tservo;\ndrivers/ptp/ptp_ocp.c-88-\tu32\t\t\t\tflash_start;\n--\ndrivers/ptp/ptp_ocp.c=243=struct board_config_reg {\n--\ndrivers/ptp/ptp_ocp.c-251-\ndrivers/ptp/ptp_ocp.c:252:struct ptp_ocp_flash_info {\ndrivers/ptp/ptp_ocp.c-253-\tconst char *name;\n--\ndrivers/ptp/ptp_ocp.c-258-\ndrivers/ptp/ptp_ocp.c:259:struct ptp_ocp_firmware_header {\ndrivers/ptp/ptp_ocp.c-260-\tchar magic[4];\n--\ndrivers/ptp/ptp_ocp.c-269-\ndrivers/ptp/ptp_ocp.c:270:struct ptp_ocp_i2c_info {\ndrivers/ptp/ptp_ocp.c-271-\tconst char *name;\n--\ndrivers/ptp/ptp_ocp.c-276-\ndrivers/ptp/ptp_ocp.c:277:struct ptp_ocp_ext_info {\ndrivers/ptp/ptp_ocp.c-278-\tint index;\n--\ndrivers/ptp/ptp_ocp.c-282-\ndrivers/ptp/ptp_ocp.c:283:struct ptp_ocp_ext_src {\ndrivers/ptp/ptp_ocp.c-284-\tvoid __iomem\t\t*mem;\ndrivers/ptp/ptp_ocp.c:285:\tstruct ptp_ocp\t\t*bp;\ndrivers/ptp/ptp_ocp.c:286:\tstruct ptp_ocp_ext_info\t*info;\ndrivers/ptp/ptp_ocp.c-287-\tint\t\t\tirq_vec;\n--\ndrivers/ptp/ptp_ocp.c-289-\ndrivers/ptp/ptp_ocp.c:290:enum ptp_ocp_sma_mode {\ndrivers/ptp/ptp_ocp.c-291-\tSMA_MODE_IN,\n--\ndrivers/ptp/ptp_ocp.c-294-\ndrivers/ptp/ptp_ocp.c:295:static struct dpll_pin_frequency ptp_ocp_sma_freq[] = {\ndrivers/ptp/ptp_ocp.c-296-\tDPLL_PIN_FREQUENCY_1PPS,\n--\ndrivers/ptp/ptp_ocp.c-301-\ndrivers/ptp/ptp_ocp.c:302:struct ptp_ocp_sma_connector {\ndrivers/ptp/ptp_ocp.c:303:\tenum\tptp_ocp_sma_mode mode;\ndrivers/ptp/ptp_ocp.c-304-\tbool\tfixed_fcn;\n--\ndrivers/ptp/ptp_ocp.c=324=struct ocp_sma_op {\ndrivers/ptp/ptp_ocp.c-325-\tconst struct ocp_selector *tbl[2];\ndrivers/ptp/ptp_ocp.c:326:\tvoid (*init)(struct ptp_ocp *bp);\ndrivers/ptp/ptp_ocp.c:327:\tu32 (*get)(struct ptp_ocp *bp, int sma_nr);\ndrivers/ptp/ptp_ocp.c:328:\tint (*set_inputs)(struct ptp_ocp *bp, int sma_nr, u32 val);\ndrivers/ptp/ptp_ocp.c:329:\tint (*set_output)(struct ptp_ocp *bp, int sma_nr, u32 val);\ndrivers/ptp/ptp_ocp.c-330-};\n--\ndrivers/ptp/ptp_ocp.c-335-\ndrivers/ptp/ptp_ocp.c:336:struct ptp_ocp_signal {\ndrivers/ptp/ptp_ocp.c-337-\tktime_t\t\tperiod;\n--\ndrivers/ptp/ptp_ocp.c-345-\ndrivers/ptp/ptp_ocp.c:346:struct ptp_ocp_serial_port {\ndrivers/ptp/ptp_ocp.c-347-\tint line;\n--\ndrivers/ptp/ptp_ocp.c=357=enum {\n--\ndrivers/ptp/ptp_ocp.c-365-\ndrivers/ptp/ptp_ocp.c:366:struct ptp_ocp {\ndrivers/ptp/ptp_ocp.c-367-\tstruct pci_dev\t\t*pdev;\n--\ndrivers/ptp/ptp_ocp.c-383-\tstruct frequency_reg\t__iomem *freq_in[OCP_FREQ_NUM];\ndrivers/ptp/ptp_ocp.c:384:\tstruct ptp_ocp_ext_src\t*signal_out[OCP_SIGNAL_NUM];\ndrivers/ptp/ptp_ocp.c:385:\tstruct ptp_ocp_ext_src\t*pps;\ndrivers/ptp/ptp_ocp.c:386:\tstruct ptp_ocp_ext_src\t*ts0;\ndrivers/ptp/ptp_ocp.c:387:\tstruct ptp_ocp_ext_src\t*ts1;\ndrivers/ptp/ptp_ocp.c:388:\tstruct ptp_ocp_ext_src\t*ts2;\ndrivers/ptp/ptp_ocp.c:389:\tstruct ptp_ocp_ext_src\t*ts3;\ndrivers/ptp/ptp_ocp.c:390:\tstruct ptp_ocp_ext_src\t*ts4;\ndrivers/ptp/ptp_ocp.c-391-\tstruct ocp_art_gpio_reg __iomem *art_sma;\n--\ndrivers/ptp/ptp_ocp.c-399-\tconst struct attribute_group **attr_group;\ndrivers/ptp/ptp_ocp.c:400:\tconst struct ptp_ocp_eeprom_map *eeprom_map;\ndrivers/ptp/ptp_ocp.c-401-\tstruct dentry\t\t*debug_root;\n--\ndrivers/ptp/ptp_ocp.c-406-\tint\t\t\tn_irqs;\ndrivers/ptp/ptp_ocp.c:407:\tstruct ptp_ocp_serial_port\tport[__PORT_COUNT];\ndrivers/ptp/ptp_ocp.c-408-\tbool\t\t\tfw_loader;\n--\ndrivers/ptp/ptp_ocp.c-418-\tu64\t\t\tfw_cap;\ndrivers/ptp/ptp_ocp.c:419:\tstruct ptp_ocp_signal\tsignal[OCP_SIGNAL_NUM];\ndrivers/ptp/ptp_ocp.c:420:\tstruct ptp_ocp_sma_connector sma[OCP_SMA_NUM];\ndrivers/ptp/ptp_ocp.c-421-\tconst struct ocp_sma_op *sma_op;\n--\ndrivers/ptp/ptp_ocp.c=437=struct ocp_resource {\n--\ndrivers/ptp/ptp_ocp.c-440-\tint irq_vec;\ndrivers/ptp/ptp_ocp.c:441:\tint (*setup)(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c-442-\tvoid *extra;\n--\ndrivers/ptp/ptp_ocp.c-446-\ndrivers/ptp/ptp_ocp.c:447:static int ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:448:static int ptp_ocp_register_i2c(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:449:static int ptp_ocp_register_spi(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:450:static int ptp_ocp_register_serial(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:451:static int ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:452:static int ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c:453:static irqreturn_t ptp_ocp_ts_irq(int irq, void *priv);\ndrivers/ptp/ptp_ocp.c:454:static irqreturn_t ptp_ocp_signal_irq(int irq, void *priv);\ndrivers/ptp/ptp_ocp.c:455:static int ptp_ocp_ts_enable(void *priv, u32 req, bool enable);\ndrivers/ptp/ptp_ocp.c:456:static int ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen,\ndrivers/ptp/ptp_ocp.c-457-\t\t\t\t      struct ptp_perout_request *req);\ndrivers/ptp/ptp_ocp.c:458:static int ptp_ocp_signal_enable(void *priv, u32 req, bool enable);\ndrivers/ptp/ptp_ocp.c:459:static int ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr);\ndrivers/ptp/ptp_ocp.c-460-\ndrivers/ptp/ptp_ocp.c:461:static int ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c-462-\ndrivers/ptp/ptp_ocp.c:463:static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r);\ndrivers/ptp/ptp_ocp.c-464-\n--\ndrivers/ptp/ptp_ocp.c=476=static const struct ocp_attr_group adva_timecard_x1_groups[];\ndrivers/ptp/ptp_ocp.c-477-\ndrivers/ptp/ptp_ocp.c:478:struct ptp_ocp_eeprom_map {\ndrivers/ptp/ptp_ocp.c-479-\tu16\toff;\n--\ndrivers/ptp/ptp_ocp.c-486-\t.off = addr,\t\t\t\t\t\t\\\ndrivers/ptp/ptp_ocp.c:487:\t.len = sizeof_field(struct ptp_ocp, member),\t\t\\\ndrivers/ptp/ptp_ocp.c:488:\t.bp_offset = offsetof(struct ptp_ocp, member)\ndrivers/ptp/ptp_ocp.c-489-\n--\ndrivers/ptp/ptp_ocp.c-493-\ndrivers/ptp/ptp_ocp.c:494:static struct ptp_ocp_eeprom_map fb_eeprom_map[] = {\ndrivers/ptp/ptp_ocp.c-495-\t{ EEPROM_ENTRY(0x43, board_id) },\n--\ndrivers/ptp/ptp_ocp.c-499-\ndrivers/ptp/ptp_ocp.c:500:static struct ptp_ocp_eeprom_map art_eeprom_map[] = {\ndrivers/ptp/ptp_ocp.c-501-\t{ EEPROM_ENTRY(0x200 + 0x43, board_id) },\n--\ndrivers/ptp/ptp_ocp.c-511-#define OCP_RES_LOCATION(member) \\\ndrivers/ptp/ptp_ocp.c:512:\t.name = #member, .bp_offset = offsetof(struct ptp_ocp, member)\ndrivers/ptp/ptp_ocp.c-513-\ndrivers/ptp/ptp_ocp.c-514-#define OCP_MEM_RESOURCE(member) \\\ndrivers/ptp/ptp_ocp.c:515:\tOCP_RES_LOCATION(member), .setup = ptp_ocp_register_mem\ndrivers/ptp/ptp_ocp.c-516-\ndrivers/ptp/ptp_ocp.c-517-#define OCP_SERIAL_RESOURCE(member) \\\ndrivers/ptp/ptp_ocp.c:518:\tOCP_RES_LOCATION(member), .setup = ptp_ocp_register_serial\ndrivers/ptp/ptp_ocp.c-519-\ndrivers/ptp/ptp_ocp.c-520-#define OCP_I2C_RESOURCE(member) \\\ndrivers/ptp/ptp_ocp.c:521:\tOCP_RES_LOCATION(member), .setup = ptp_ocp_register_i2c\ndrivers/ptp/ptp_ocp.c-522-\ndrivers/ptp/ptp_ocp.c-523-#define OCP_SPI_RESOURCE(member) \\\ndrivers/ptp/ptp_ocp.c:524:\tOCP_RES_LOCATION(member), .setup = ptp_ocp_register_spi\ndrivers/ptp/ptp_ocp.c-525-\ndrivers/ptp/ptp_ocp.c-526-#define OCP_EXT_RESOURCE(member) \\\ndrivers/ptp/ptp_ocp.c:527:\tOCP_RES_LOCATION(member), .setup = ptp_ocp_register_ext\ndrivers/ptp/ptp_ocp.c-528-\n--\ndrivers/ptp/ptp_ocp.c=556=static struct ocp_resource ocp_fb_resource[] = {\n--\ndrivers/ptp/ptp_ocp.c-563-\t\t.offset = 0x01010000, .size = 0x10000, .irq_vec = 1,\ndrivers/ptp/ptp_ocp.c:564:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-565-\t\t\t.index = 0,\ndrivers/ptp/ptp_ocp.c:566:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:567:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-568-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-572-\t\t.offset = 0x01020000, .size = 0x10000, .irq_vec = 2,\ndrivers/ptp/ptp_ocp.c:573:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-574-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:575:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:576:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-577-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-581-\t\t.offset = 0x01060000, .size = 0x10000, .irq_vec = 6,\ndrivers/ptp/ptp_ocp.c:582:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-583-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:584:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:585:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-586-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-590-\t\t.offset = 0x01110000, .size = 0x10000, .irq_vec = 15,\ndrivers/ptp/ptp_ocp.c:591:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-592-\t\t\t.index = 3,\ndrivers/ptp/ptp_ocp.c:593:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:594:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-595-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-599-\t\t.offset = 0x01120000, .size = 0x10000, .irq_vec = 16,\ndrivers/ptp/ptp_ocp.c:600:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-601-\t\t\t.index = 4,\ndrivers/ptp/ptp_ocp.c:602:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:603:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-604-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-609-\t\t.offset = 0x010C0000, .size = 0x10000, .irq_vec = 0,\ndrivers/ptp/ptp_ocp.c:610:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-611-\t\t\t.index = 5,\ndrivers/ptp/ptp_ocp.c:612:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:613:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-614-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-618-\t\t.offset = 0x010D0000, .size = 0x10000, .irq_vec = 11,\ndrivers/ptp/ptp_ocp.c:619:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-620-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:621:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:622:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-623-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-627-\t\t.offset = 0x010E0000, .size = 0x10000, .irq_vec = 12,\ndrivers/ptp/ptp_ocp.c:628:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-629-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:630:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:631:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-632-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-636-\t\t.offset = 0x010F0000, .size = 0x10000, .irq_vec = 13,\ndrivers/ptp/ptp_ocp.c:637:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-638-\t\t\t.index = 3,\ndrivers/ptp/ptp_ocp.c:639:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:640:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-641-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-645-\t\t.offset = 0x01100000, .size = 0x10000, .irq_vec = 14,\ndrivers/ptp/ptp_ocp.c:646:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-647-\t\t\t.index = 4,\ndrivers/ptp/ptp_ocp.c:648:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:649:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-650-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-702-\t\t.offset = 0x00150000, .size = 0x10000, .irq_vec = 7,\ndrivers/ptp/ptp_ocp.c:703:\t\t.extra = \u0026(struct ptp_ocp_i2c_info) {\ndrivers/ptp/ptp_ocp.c-704-\t\t\t.name = \"xiic-i2c\",\n--\ndrivers/ptp/ptp_ocp.c-719-\t\t.offset = 0x00160000 + 0x1000, .irq_vec = 3,\ndrivers/ptp/ptp_ocp.c:720:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-721-\t\t\t.baud = 115200,\n--\ndrivers/ptp/ptp_ocp.c-726-\t\t.offset = 0x00170000 + 0x1000, .irq_vec = 4,\ndrivers/ptp/ptp_ocp.c:727:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-728-\t\t\t.baud = 115200,\n--\ndrivers/ptp/ptp_ocp.c-733-\t\t.offset = 0x00180000 + 0x1000, .irq_vec = 5,\ndrivers/ptp/ptp_ocp.c:734:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-735-\t\t\t.baud = 57600,\n--\ndrivers/ptp/ptp_ocp.c-744-\t\t.offset = 0x00310000, .size = 0x10000, .irq_vec = 9,\ndrivers/ptp/ptp_ocp.c:745:\t\t.extra = \u0026(struct ptp_ocp_flash_info) {\ndrivers/ptp/ptp_ocp.c-746-\t\t\t.name = \"xilinx_spi\", .pci_offset = 0,\n--\ndrivers/ptp/ptp_ocp.c-775-\t{\ndrivers/ptp/ptp_ocp.c:776:\t\t.setup = ptp_ocp_fb_board_init,\ndrivers/ptp/ptp_ocp.c:777:\t\t.extra = \u0026(struct ptp_ocp_servo_conf) {\ndrivers/ptp/ptp_ocp.c-778-\t\t\t.servo_offset_p = 0x2000,\n--\ndrivers/ptp/ptp_ocp.c=797=static struct ocp_resource ocp_art_resource[] = {\n--\ndrivers/ptp/ptp_ocp.c-804-\t\t.offset = 0x00160000 + 0x1000, .irq_vec = 3,\ndrivers/ptp/ptp_ocp.c:805:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-806-\t\t\t.baud = 115200,\n--\ndrivers/ptp/ptp_ocp.c-816-\t\t.offset = 0x360000, .size = 0x20, .irq_vec = 12,\ndrivers/ptp/ptp_ocp.c:817:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-818-\t\t\t.index = 0,\ndrivers/ptp/ptp_ocp.c:819:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:820:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-821-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-825-\t\t.offset = 0x380000, .size = 0x20, .irq_vec = 8,\ndrivers/ptp/ptp_ocp.c:826:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-827-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:828:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:829:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-830-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-834-\t\t.offset = 0x390000, .size = 0x20, .irq_vec = 10,\ndrivers/ptp/ptp_ocp.c:835:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-836-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:837:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:838:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-839-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-843-\t\t.offset = 0x3A0000, .size = 0x20, .irq_vec = 14,\ndrivers/ptp/ptp_ocp.c:844:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-845-\t\t\t.index = 3,\ndrivers/ptp/ptp_ocp.c:846:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:847:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-848-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-852-\t\t.offset = 0x3B0000, .size = 0x20, .irq_vec = 15,\ndrivers/ptp/ptp_ocp.c:853:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-854-\t\t\t.index = 4,\ndrivers/ptp/ptp_ocp.c:855:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:856:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-857-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-862-\t\t.offset = 0x00330000, .size = 0x20, .irq_vec = 11,\ndrivers/ptp/ptp_ocp.c:863:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-864-\t\t\t.index = 5,\ndrivers/ptp/ptp_ocp.c:865:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:866:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-867-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-871-\t\t.offset = 0x00310000, .size = 0x10000, .irq_vec = 9,\ndrivers/ptp/ptp_ocp.c:872:\t\t.extra = \u0026(struct ptp_ocp_flash_info) {\ndrivers/ptp/ptp_ocp.c-873-\t\t\t.name = \"spi_altera\", .pci_offset = 0,\n--\ndrivers/ptp/ptp_ocp.c-886-\t\t.offset = 0x350000, .size = 0x100, .irq_vec = 4,\ndrivers/ptp/ptp_ocp.c:887:\t\t.extra = \u0026(struct ptp_ocp_i2c_info) {\ndrivers/ptp/ptp_ocp.c-888-\t\t\t.name = \"ocores-i2c\",\n--\ndrivers/ptp/ptp_ocp.c-903-\t\t.offset = 0x00190000, .irq_vec = 7,\ndrivers/ptp/ptp_ocp.c:904:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-905-\t\t\t.baud = 9600,\n--\ndrivers/ptp/ptp_ocp.c-912-\t{\ndrivers/ptp/ptp_ocp.c:913:\t\t.setup = ptp_ocp_art_board_init,\ndrivers/ptp/ptp_ocp.c:914:\t\t.extra = \u0026(struct ptp_ocp_servo_conf) {\ndrivers/ptp/ptp_ocp.c-915-\t\t\t.servo_offset_p = 0x2000,\n--\ndrivers/ptp/ptp_ocp.c=924=static struct ocp_resource ocp_adva_resource[] = {\n--\ndrivers/ptp/ptp_ocp.c-931-\t\t.offset = 0x01010000, .size = 0x10000, .irq_vec = 1,\ndrivers/ptp/ptp_ocp.c:932:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-933-\t\t\t.index = 0,\ndrivers/ptp/ptp_ocp.c:934:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:935:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-936-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-940-\t\t.offset = 0x01020000, .size = 0x10000, .irq_vec = 2,\ndrivers/ptp/ptp_ocp.c:941:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-942-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:943:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:944:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-945-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-949-\t\t.offset = 0x01060000, .size = 0x10000, .irq_vec = 6,\ndrivers/ptp/ptp_ocp.c:950:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-951-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:952:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:953:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-954-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-959-\t\t.offset = 0x010C0000, .size = 0x10000, .irq_vec = 0,\ndrivers/ptp/ptp_ocp.c:960:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-961-\t\t\t.index = 5,\ndrivers/ptp/ptp_ocp.c:962:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:963:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-964-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-968-\t\t.offset = 0x010D0000, .size = 0x10000, .irq_vec = 11,\ndrivers/ptp/ptp_ocp.c:969:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-970-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:971:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:972:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-973-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-977-\t\t.offset = 0x010E0000, .size = 0x10000, .irq_vec = 12,\ndrivers/ptp/ptp_ocp.c:978:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-979-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:980:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:981:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-982-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1014-\t\t.offset = 0x00160000 + 0x1000, .irq_vec = 3,\ndrivers/ptp/ptp_ocp.c:1015:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-1016-\t\t\t.baud = 9600,\n--\ndrivers/ptp/ptp_ocp.c-1021-\t\t.offset = 0x00180000 + 0x1000, .irq_vec = 5,\ndrivers/ptp/ptp_ocp.c:1022:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-1023-\t\t\t.baud = 115200,\n--\ndrivers/ptp/ptp_ocp.c-1036-\t\t.offset = 0x00310400, .size = 0x10000, .irq_vec = 9,\ndrivers/ptp/ptp_ocp.c:1037:\t\t.extra = \u0026(struct ptp_ocp_flash_info) {\ndrivers/ptp/ptp_ocp.c-1038-\t\t\t.name = \"spi_altera\", .pci_offset = 0,\n--\ndrivers/ptp/ptp_ocp.c-1051-\t\t.offset = 0x150000, .size = 0x100, .irq_vec = 7,\ndrivers/ptp/ptp_ocp.c:1052:\t\t.extra = \u0026(struct ptp_ocp_i2c_info) {\ndrivers/ptp/ptp_ocp.c-1053-\t\t\t.name = \"ocores-i2c\",\n--\ndrivers/ptp/ptp_ocp.c-1070-\t{\ndrivers/ptp/ptp_ocp.c:1071:\t\t.setup = ptp_ocp_adva_board_init,\ndrivers/ptp/ptp_ocp.c:1072:\t\t.extra = \u0026(struct ptp_ocp_adva_info) {\ndrivers/ptp/ptp_ocp.c-1073-\t\t\t.servo = {\n--\ndrivers/ptp/ptp_ocp.c=1089=static struct ocp_resource ocp_adva_x1_resource[] = {\n--\ndrivers/ptp/ptp_ocp.c-1096-\t\t.offset = 0x01010000, .size = 0x10000, .irq_vec = 1,\ndrivers/ptp/ptp_ocp.c:1097:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1098-\t\t\t.index = 0,\ndrivers/ptp/ptp_ocp.c:1099:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1100:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1101-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1105-\t\t.offset = 0x01020000, .size = 0x10000, .irq_vec = 2,\ndrivers/ptp/ptp_ocp.c:1106:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1107-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:1108:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1109:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1110-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1114-\t\t.offset = 0x01060000, .size = 0x10000, .irq_vec = 6,\ndrivers/ptp/ptp_ocp.c:1115:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1116-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:1117:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1118:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1119-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1123-\t\t.offset = 0x01110000, .size = 0x10000, .irq_vec = 15,\ndrivers/ptp/ptp_ocp.c:1124:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1125-\t\t\t.index = 3,\ndrivers/ptp/ptp_ocp.c:1126:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1127:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1128-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1132-\t\t.offset = 0x01120000, .size = 0x10000, .irq_vec = 16,\ndrivers/ptp/ptp_ocp.c:1133:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1134-\t\t\t.index = 4,\ndrivers/ptp/ptp_ocp.c:1135:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1136:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1137-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1142-\t\t.offset = 0x010C0000, .size = 0x10000, .irq_vec = 0,\ndrivers/ptp/ptp_ocp.c:1143:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1144-\t\t\t.index = 5,\ndrivers/ptp/ptp_ocp.c:1145:\t\t\t.irq_fcn = ptp_ocp_ts_irq,\ndrivers/ptp/ptp_ocp.c:1146:\t\t\t.enable = ptp_ocp_ts_enable,\ndrivers/ptp/ptp_ocp.c-1147-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1151-\t\t.offset = 0x010D0000, .size = 0x10000, .irq_vec = 11,\ndrivers/ptp/ptp_ocp.c:1152:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1153-\t\t\t.index = 1,\ndrivers/ptp/ptp_ocp.c:1154:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:1155:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-1156-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1160-\t\t.offset = 0x010E0000, .size = 0x10000, .irq_vec = 12,\ndrivers/ptp/ptp_ocp.c:1161:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1162-\t\t\t.index = 2,\ndrivers/ptp/ptp_ocp.c:1163:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:1164:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-1165-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1169-\t\t.offset = 0x010F0000, .size = 0x10000, .irq_vec = 13,\ndrivers/ptp/ptp_ocp.c:1170:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1171-\t\t\t.index = 3,\ndrivers/ptp/ptp_ocp.c:1172:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:1173:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-1174-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1178-\t\t.offset = 0x01100000, .size = 0x10000, .irq_vec = 14,\ndrivers/ptp/ptp_ocp.c:1179:\t\t.extra = \u0026(struct ptp_ocp_ext_info) {\ndrivers/ptp/ptp_ocp.c-1180-\t\t\t.index = 4,\ndrivers/ptp/ptp_ocp.c:1181:\t\t\t.irq_fcn = ptp_ocp_signal_irq,\ndrivers/ptp/ptp_ocp.c:1182:\t\t\t.enable = ptp_ocp_signal_enable,\ndrivers/ptp/ptp_ocp.c-1183-\t\t},\n--\ndrivers/ptp/ptp_ocp.c-1215-\t\t.offset = 0x00160000 + 0x1000, .irq_vec = 3,\ndrivers/ptp/ptp_ocp.c:1216:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-1217-\t\t\t.baud = 9600,\n--\ndrivers/ptp/ptp_ocp.c-1222-\t\t.offset = 0x00180000 + 0x1000, .irq_vec = 5,\ndrivers/ptp/ptp_ocp.c:1223:\t\t.extra = \u0026(struct ptp_ocp_serial_port) {\ndrivers/ptp/ptp_ocp.c-1224-\t\t\t.baud = 115200,\n--\ndrivers/ptp/ptp_ocp.c-1245-\t\t.offset = 0x00310000, .size = 0x10000, .irq_vec = 9,\ndrivers/ptp/ptp_ocp.c:1246:\t\t.extra = \u0026(struct ptp_ocp_flash_info) {\ndrivers/ptp/ptp_ocp.c-1247-\t\t\t.name = \"xilinx_spi\", .pci_offset = 0,\n--\ndrivers/ptp/ptp_ocp.c-1262-\t\t.offset = 0x00150000, .size = 0x10000, .irq_vec = 7,\ndrivers/ptp/ptp_ocp.c:1263:\t\t.extra = \u0026(struct ptp_ocp_i2c_info) {\ndrivers/ptp/ptp_ocp.c-1264-\t\t\t.name = \"xiic-i2c\",\n--\ndrivers/ptp/ptp_ocp.c-1277-\t{\ndrivers/ptp/ptp_ocp.c:1278:\t\t.setup = ptp_ocp_adva_board_init,\ndrivers/ptp/ptp_ocp.c:1279:\t\t.extra = \u0026(struct ptp_ocp_adva_info) {\ndrivers/ptp/ptp_ocp.c-1280-\t\t\t.servo = {\n--\ndrivers/ptp/ptp_ocp.c-1296-\ndrivers/ptp/ptp_ocp.c:1297:static const struct pci_device_id ptp_ocp_pcidev_id[] = {\ndrivers/ptp/ptp_ocp.c-1298-\t{ PCI_DEVICE_DATA(META, TIMECARD, \u0026ocp_fb_resource) },\n--\ndrivers/ptp/ptp_ocp.c-1304-};\ndrivers/ptp/ptp_ocp.c:1305:MODULE_DEVICE_TABLE(pci, ptp_ocp_pcidev_id);\ndrivers/ptp/ptp_ocp.c-1306-\ndrivers/ptp/ptp_ocp.c:1307:static DEFINE_MUTEX(ptp_ocp_lock);\ndrivers/ptp/ptp_ocp.c:1308:static DEFINE_IDR(ptp_ocp_idr);\ndrivers/ptp/ptp_ocp.c-1309-\ndrivers/ptp/ptp_ocp.c:1310:static const struct ocp_selector ptp_ocp_clock[] = {\ndrivers/ptp/ptp_ocp.c-1311-\t{ .name = \"NONE\",\t.value = 0 },\n--\ndrivers/ptp/ptp_ocp.c-1326-\ndrivers/ptp/ptp_ocp.c:1327:static const struct ocp_selector ptp_ocp_sma_in[] = {\ndrivers/ptp/ptp_ocp.c-1328-\t{ .name = \"10Mhz\",  .value = 0x0000,      .frequency = 10000000 },\n\n"
}

5/2 2026/08/03 19:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 24980
							output: 27
							thoughts: 227
						

Thoughts:
**Analyzing the PTP OCP Time Card Driver**

Okay, so I'm looking at this `ptp_ocp.c` driver. It's the "Open Compute Project time card driver", so it's a PCI device driver, which is the first thing I notice. It's registering itself as such. The patch adds firmware upload functionality using the `firmware_upload` framework. Interesting. The immediate question is, can I even *reach* this driver in a standard QEMU environment?

Right, it's a PCI driver. It binds to specific PCI IDs: `PCI_DEVICE_ID_META_TIMECARD` (0x0400), `PCI_DEVICE_ID_OROLIA_ART_TIMECARD` (0x0400), and `PCI_DEVICE_ID_ADVA_TIMECARD` (0x0410). So, it's not going to be a general-purpose driver; it's specific hardware.

But, hang on... can syzkaller fuzz this? Syzkaller has this pseudo-PCI subsystem, doesn't it? It can inject PCI devices with arbitrary vendor/device IDs if it has descriptions for them. That could open up an interesting attack surface. The critical question now is, does syzkaller have any descriptions for `ptp_ocp`? I need to check the syzkaller descriptions.



6/2 2026/08/03 19:41 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "ptp_ocp",
  "PathPrefix": "sys/"
}

Results:
{
  "error": "no matches"
}

7/2 2026/08/03 19:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 25551
							output: 132
							thoughts: 1852
						

Thoughts:
**WorthFuzzing=false Decision - ptp_ocp Driver Analysis**

Okay, let's break this down. First, I need to remember the restrictions – no syzkaller pseudo-syscalls or syzlang descriptions. Got it. And I don't have those special `syz-grepper` or `read-syz-spec` tools, so I'll work with what I *do* have.  

Now, about this `ptp_ocp` driver. Is it vendor-specific? It’s for the Open Compute Project time card, a specific PCIe hardware card.  Does it *require* physical hardware? Ah, that's the key.  Syzkaller's pseudo-PCI only emulates the PCI config space and basic BARs, not the actual device's internal logic like the CPLD, I2C bus, and MicroBlaze firmware. This patch interacts with hardware registers.

This patch adds I2C communication with a CPLD. Looking at the code: `adva_x1_mblaze_acquire` expects specific responses (`MBLAZE_GRANTED`). This code uses `iowrite32` and `ioread32` to interact with the hardware and waits for a specific response.  In a virtualized environment, those `ioread32` calls will likely return zero or `0xffffffff`, so `adva_x1_mblaze_acquire` will almost certainly fail with timeout. If it fails, all the subsequent code, I2C transfers, CPLD commands, and firmware uploads, will be completely unreachable. And the `adva_cpld_write` calls `adva_x1_i2c_xfer`.

The prompt gives a couple of specific reasons for `WorthFuzzing=false`. It says: "Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU". And, "Code paths that are impossible to reach in virtualized environments like GCE or QEMU". Since `ptp_ocp` is a driver for the OCP Timecard, which is a *physical* PCIe card, and the new code directly communicates with this hardware (MicroBlaze, I2C mux, CPLD) that's not emulated in QEMU, it falls squarely into that first category. This code is impossible to reach in a virtualized environment because it explicitly waits for the hardware to be in a certain state, and that state can't be achieved without the actual hardware.  

Even if it gets past the MicroBlaze grant, the `i2c_transfer` will fail because the hardware I2C controller is not emulated or possibly not even registered. So, there is no way to reach this code in a virtualized environment without the physical hardware. Therefore, `WorthFuzzing = false`.

I need to confirm that these changes are contained within that driver and don't introduce any generic kernel modifications. Looks like I'm good: the changes are limited to `Documentation/ABI/testing/sysfs-timecard` and `drivers/ptp/ptp_ocp.c`. No generic changes.
Ok, I will formulate the response.



8/2 2026/08/03 19:41 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch adds CPLD firmware upload and sysfs attributes for the ADVA x1 OCP Timecard, which is a physical PCIe device. The new code heavily relies on hardware-specific interactions (e.g., polling MMIO registers for MicroBlaze firmware grants, I2C communication with a PCA9548 mux and Lattice CPLD) that are not emulated in standard QEMU environments. Consequently, the core logic is unreachable during fuzzing without the physical hardware.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds CPLD firmware upload and sysfs attributes for the ADVA x1 OCP Timecard, which is a physical PCIe device. The new code heavily relies on hardware-specific interactions (e.g., polling MMIO registers for MicroBlaze firmware grants, I2C communication with a PCA9548 mux and Lattice CPLD) that are not emulated in standard QEMU environments. Consequently, the core logic is unreachable during fuzzing without the physical hardware.",
  "WorthFuzzing": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)