in ctl.c [427:501]
static void tb_ctl_rx_callback(struct tb_ring *ring, struct ring_frame *frame,
bool canceled)
{
struct ctl_pkg *pkg = container_of(frame, typeof(*pkg), frame);
struct tb_cfg_request *req;
__be32 crc32;
if (canceled)
return; /*
* ring is stopped, packet is referenced from
* ctl->rx_packets.
*/
if (frame->size < 4 || frame->size % 4 != 0) {
tb_ctl_err(pkg->ctl, "RX: invalid size %#x, dropping packet\n",
frame->size);
goto rx;
}
frame->size -= 4; /* remove checksum */
crc32 = tb_crc(pkg->buffer, frame->size);
be32_to_cpu_array(pkg->buffer, pkg->buffer, frame->size / 4);
switch (frame->eof) {
case TB_CFG_PKG_READ:
case TB_CFG_PKG_WRITE:
case TB_CFG_PKG_ERROR:
case TB_CFG_PKG_OVERRIDE:
case TB_CFG_PKG_RESET:
if (*(__be32 *)(pkg->buffer + frame->size) != crc32) {
tb_ctl_err(pkg->ctl,
"RX: checksum mismatch, dropping packet\n");
goto rx;
}
if (tb_async_error(pkg)) {
tb_ctl_handle_event(pkg->ctl, frame->eof,
pkg, frame->size);
goto rx;
}
break;
case TB_CFG_PKG_EVENT:
case TB_CFG_PKG_XDOMAIN_RESP:
case TB_CFG_PKG_XDOMAIN_REQ:
if (*(__be32 *)(pkg->buffer + frame->size) != crc32) {
tb_ctl_err(pkg->ctl,
"RX: checksum mismatch, dropping packet\n");
goto rx;
}
fallthrough;
case TB_CFG_PKG_ICM_EVENT:
if (tb_ctl_handle_event(pkg->ctl, frame->eof, pkg, frame->size))
goto rx;
break;
default:
break;
}
/*
* The received packet will be processed only if there is an
* active request and that the packet is what is expected. This
* prevents packets such as replies coming after timeout has
* triggered from messing with the active requests.
*/
req = tb_cfg_request_find(pkg->ctl, pkg);
if (req) {
if (req->copy(req, pkg))
schedule_work(&req->work);
tb_cfg_request_put(req);
}
rx:
tb_ctl_rx_submit(pkg);
}