diff --git a/drivers/ethernet/eth_adin2111.c b/drivers/ethernet/eth_adin2111.c index 536209a84efc4..0f125fabc2d4b 100644 --- a/drivers/ethernet/eth_adin2111.c +++ b/drivers/ethernet/eth_adin2111.c @@ -317,7 +317,7 @@ int eth_adin2111_oa_data_read(const struct device *dev, const uint16_t port_idx) K_MSEC(CONFIG_ETH_ADIN2111_TIMEOUT)); if (!pkt) { LOG_ERR("OA RX: cannot allcate packet space, skipping."); - return -EIO; + return -ENOMEM; } /* Skipping CRC32 */ ret = net_pkt_write(pkt, ctx->buf, ctx->scur - sizeof(uint32_t)); @@ -351,7 +351,7 @@ static int eth_adin2111_send_oa_frame(const struct device *dev, struct net_pkt * uint16_t clen, len = net_pkt_get_len(pkt); uint32_t hdr; uint8_t chunks, i; - int ret, txc, cur; + int ret, txc, cur, ebo; chunks = len / ctx->oa_cps; @@ -359,6 +359,17 @@ static int eth_adin2111_send_oa_frame(const struct device *dev, struct net_pkt * chunks++; } + if (chunks > 1) { + /* we have to calculate EBO so we do not exceed maximum Ethernet frame length */ + ebo = (len % ctx->oa_cps) - 1; + if (ebo < 0) { + ebo += ctx->oa_cps; + } + } else { + /* we have to pad to the minimum Ethernet frame length */ + ebo = ctx->oa_cps - 1; + } + ret = eth_adin2111_reg_read(dev, ADIN2111_BUFSTS, &txc); if (ret < 0) { LOG_ERR("Cannot read txc"); @@ -380,7 +391,7 @@ static int eth_adin2111_send_oa_frame(const struct device *dev, struct net_pkt * } if (i == chunks) { hdr |= ADIN2111_OA_DATA_HDR_EV; - hdr |= (ctx->oa_cps - 1) << ADIN2111_OA_DATA_HDR_EBO; + hdr |= ebo << ADIN2111_OA_DATA_HDR_EBO; } hdr |= eth_adin2111_oa_get_parity(hdr); @@ -693,58 +704,47 @@ static void adin2111_offload_thread(void *p1, void *p2, void *p3) adin2111_port_on_phyint(ctx->port[1]); } - if (ctx->oa) { - if (status1 & ADIN2111_STATUS1_P1_RX_RDY) { - ret = eth_adin2111_oa_data_read(dev, 0); - if (ret < 0) { - goto continue_unlock; - } - } - if (is_adin2111 && (status1 & ADIN2111_STATUS1_P2_RX_RDY)) { - ret = eth_adin2111_oa_data_read(dev, 1); - if (ret < 0) { - goto continue_unlock; - } - } - } else { + if (!ctx->oa) { #if CONFIG_ETH_ADIN2111_SPI_CFG0 if (status0 & ADIN2111_STATUS1_SPI_ERR) { LOG_WRN("Detected TX SPI CRC error"); } -#endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */ +#endif + } + /* handle rx interrupt(s) */ + do { /* handle port 1 rx */ if (status1 & ADIN2111_STATUS1_P1_RX_RDY) { - do { + if (ctx->oa) { + ret = eth_adin2111_oa_data_read(dev, 0); + } else { ret = adin2111_read_fifo(dev, 0U); - if (ret < 0) { - break; - } - - ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, - &status1); - if (ret < 0) { - goto continue_unlock; - } - } while (!!(status1 & ADIN2111_STATUS1_P1_RX_RDY)); + } + + if (ret < 0) { + break; + } } /* handle port 2 rx */ if (is_adin2111 && (status1 & ADIN2111_STATUS1_P2_RX_RDY)) { - do { + if (ctx->oa) { + ret = eth_adin2111_oa_data_read(dev, 1); + } else { ret = adin2111_read_fifo(dev, 1U); - if (ret < 0) { - break; - } - - ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, - &status1); - if (ret < 0) { - goto continue_unlock; - } - } while (!!(status1 & ADIN2111_STATUS1_P2_RX_RDY)); + } + + if (ret < 0) { + break; + } } - } + + ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1); + if (ret < 0) { + break; + } + } while (status1 & (ADIN2111_STATUS1_P1_RX_RDY | ADIN2111_STATUS1_P2_RX_RDY)); continue_unlock: /* clear interrupts */