summaryrefslogtreecommitdiffstats
path: root/scripts/syscallnr.sh
diff options
context:
space:
mode:
authorAbdurrahman Hussain <abdurrahman@nexthop.ai>2026-09-24 17:10:35 -0700
committerAndi Shyti <andi.shyti@kernel.org>2026-09-28 01:28:25 +0200
commitb7e6df2f52ed5c02838832f53c171a5645f9b376 (patch)
tree62b8701c81117a188a0b17fc2629b6cf7ed2a6df /scripts/syscallnr.sh
parent72d3fcf802c45d00b300f25b848a93c3a2bd7c7e (diff)
downloadlinux-stable-b7e6df2f52ed5c02838832f53c171a5645f9b376.tar.gz
linux-stable-b7e6df2f52ed5c02838832f53c171a5645f9b376.zip
i2c: xiic: preserve PEC byte length in SMBus block read setup
xiic_smbus_block_read_setup() recalculates i2c->rx_msg->len based on the length byte returned by the device, but historically clobbered the PEC byte expectation the SMBus core had baked into msg->len. That dropped the PEC byte from the caller's buffer on the normal and chunked receive-fifo branches. Compute pec_len up-front as (i2c->rx_msg->len - 1) -- the trailing bytes the caller has already accounted for beyond the length byte, 1 when the SMBus core enabled PEC, and possibly more for an I2C_M_RECV_LEN request coming from i2c-dev -- and add it to the new length in every branch: - chunked: the trailing bytes do not fit in the Rx FIFO, so drain in chunks. The guard becomes (rxmsg_len + pec_len > IIC_RX_FIFO_DEPTH) rather than rxmsg_len alone, both because pec_len bytes also have to fit and because it is what bounds rfd_set in the else branch below to the 4 bits of XIIC_RFD_REG_OFFSET. - padded (1 + rxmsg_len + pec_len < SMBUS_BLOCK_READ_MIN_LEN): the hardware needs at least 3 bytes on the bus to exit the read cleanly (the second byte is already being clocked in by the time the ISR reads the length byte and is too late to NACK), so we still pad rx_msg->len up to SMBUS_BLOCK_READ_MIN_LEN. The dummy trailing byte that gets drained must then be trimmed off before handing the message back to the SMBus core; otherwise i2c_smbus_check_pec() reads buf[len-1] (= dummy) instead of the real PEC byte at buf[1] and rejects every clean zero-length block read with -EBADMSG. Record the true valid byte count in a new field i2c->smbus_actual_len and trim rx_msg->len down to it in xiic_smbus_trim_len(), called from both completion sites that clear rx_msg: xiic_process()'s RX_FULL branch and xiic_recv_atomic(), which drains the FIFO with interrupts off. smbus_actual_len is per-receive state, so xiic_start_recv() clears it before every receive. Only the padded branch ever sets it, and a block read aborted by arbitration loss or a TX error never reaches the completion site, so without that clear a stale value would trim the length of an unrelated later read. The condition is expressed in total bytes rather than the old "(rxmsg_len == 1) || (rxmsg_len == 0)" so that a request carrying more than one trailing byte does not get padded: padding records a length the drain never reaches, which would hand the caller a byte that was never received. - normal: all trailing bytes fit in one FIFO fill. rfd_set gains pec_len for the same reason the length does. Because the padded branch above has already taken every case with fewer than SMBUS_BLOCK_READ_MIN_LEN total bytes, rxmsg_len + pec_len is at least 2 here and the subtraction cannot underflow the u8. Fixes: e4c1ff772e1a ("i2c: xiic: Add smbus_block_read functionality") Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai> Cc: <stable@vger.kernel.org> # v6.3+ Acked-by: Michal Simek <michal.simek@amd.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://patch.msgid.link/20260924-i2c-xiic-v7-1-df7e752332ef@nexthop.ai
Diffstat (limited to 'scripts/syscallnr.sh')
0 files changed, 0 insertions, 0 deletions