diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index 49b6765a..4eec8a78 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -1653,7 +1653,7 @@ static int ether_tx_swcx_alloc(struct device *dev, /* Map the linear buffers from the skb first. * For TSO only upto TCP header is filled in first desc. */ - while (len) { + while (valid_tx_len(len)) { tx_swcx = tx_ring->tx_swcx + cur_tx_idx; if (unlikely(tx_swcx->len)) { goto desc_not_free; @@ -1685,7 +1685,7 @@ static int ether_tx_swcx_alloc(struct device *dev, */ if ((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) { len = skb_headlen(skb) - tx_pkt_cx->total_hdrlen; - while (len) { + while (valid_tx_len(len)) { tx_swcx = tx_ring->tx_swcx + cur_tx_idx; if (unlikely(tx_swcx->len)) { @@ -1719,7 +1719,7 @@ static int ether_tx_swcx_alloc(struct device *dev, offset = 0; frag = &skb_shinfo(skb)->frags[i]; len = skb_frag_size(frag); - while (len) { + while (valid_tx_len(len)) { tx_swcx = tx_ring->tx_swcx + cur_tx_idx; if (unlikely(tx_swcx->len)) { goto desc_not_free; @@ -1759,7 +1759,7 @@ desc_not_free: dma_map_failed: /* Failed to fill current desc. Rollback previous desc's */ - while (cnt) { + while (cnt > 0) { DECR_TX_DESC_INDEX(cur_tx_idx, 1U); tx_swcx = tx_ring->tx_swcx + cur_tx_idx; if (tx_swcx->buf_phy_addr) { diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h index 7be6f969..32ad7997 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h @@ -121,10 +121,34 @@ #define ETHER_DEFAULT_PLATFORM_MTU 1500U /** - * @brief Maximum buffer length per DMA descriptor (4KB). + * @brief Maximum buffer length per DMA descriptor (16KB). */ #define ETHER_TX_MAX_BUFF_SIZE 0x3FFF +/** + * @brief Maximum skb frame(GSO/TSO) size (64KB) + */ +#define ETHER_TX_MAX_FRAME_SIZE GSO_MAX_SIZE + +/** + * @brief Check if Tx data buffer length is within bounds. + * + * Algorithm: Check the data length if it is valid. + * + * @param[in] length: Tx data buffer length to check + * + * @retval true if length is valid + * @retval false otherwise + */ +static inline bool valid_tx_len(unsigned int length) +{ + if (length > 0U && length <= ETHER_TX_MAX_FRAME_SIZE) { + return true; + } else { + return false; + } +} + /* Descriptors required for maximum contiguous TSO/GSO packet * one extra descriptor if there is linear buffer payload */ diff --git a/drivers/net/ethernet/nvidia/nvethernet/osd.c b/drivers/net/ethernet/nvidia/nvethernet/osd.c index 523c79bb..d02b9573 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/osd.c +++ b/drivers/net/ethernet/nvidia/nvethernet/osd.c @@ -190,7 +190,8 @@ static void ether_realloc_rx_skb(struct ether_priv_data *pdata, unsigned int local_refill_idx = rx_ring->refill_idx; int ret = 0; - while (local_refill_idx != rx_ring->cur_rx_idx) { + while (local_refill_idx != rx_ring->cur_rx_idx && + local_refill_idx < RX_DESC_CNT) { rx_swcx = rx_ring->rx_swcx + local_refill_idx; rx_desc = rx_ring->rx_desc + local_refill_idx;