From: Dmitry Bogdanov Date: Sat, 25 May 2019 09:58:01 +0000 (+0000) Subject: net: aquantia: check rx csum for all packets in LRO session X-Git-Tag: v5.2-rc3~26^2~23^2~2 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=f38f1ee8aeb2c19f65fc29de49bed231a868198c;p=linux.git net: aquantia: check rx csum for all packets in LRO session Atlantic hardware does not aggregate nor breaks LRO sessions with bad csum packets. This means driver should take care of that. If in LRO session there is a non-first descriptor with invalid checksum (L2/L3/L4), the driver must account this information in csum application logic. Fixes: 018423e90bee8 ("net: ethernet: aquantia: Add ring support code") Signed-off-by: Igor Russkikh Signed-off-by: Dmitry Bogdanov Signed-off-by: David S. Miller --- diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 63ed00415904..941b0beb87ef 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -299,35 +299,47 @@ int aq_ring_rx_clean(struct aq_ring_s *self, unsigned int i = 0U; u16 hdr_len; - if (buff->is_error) - continue; - if (buff->is_cleaned) continue; if (!buff->is_eop) { - for (next_ = buff->next, - buff_ = &self->buff_ring[next_]; true; - next_ = buff_->next, - buff_ = &self->buff_ring[next_]) { + buff_ = buff; + do { + next_ = buff_->next, + buff_ = &self->buff_ring[next_]; is_rsc_completed = aq_ring_dx_in_range(self->sw_head, next_, self->hw_head); - if (unlikely(!is_rsc_completed)) { - is_rsc_completed = false; + if (unlikely(!is_rsc_completed)) break; - } - if (buff_->is_eop) - break; - } + buff->is_error |= buff_->is_error; + + } while (!buff_->is_eop); if (!is_rsc_completed) { err = 0; goto err_exit; } + if (buff->is_error) { + buff_ = buff; + do { + next_ = buff_->next, + buff_ = &self->buff_ring[next_]; + + buff_->is_cleaned = true; + } while (!buff_->is_eop); + + ++self->stats.rx.errors; + continue; + } + } + + if (buff->is_error) { + ++self->stats.rx.errors; + continue; } dma_sync_single_range_for_cpu(aq_nic_get_dev(self->aq_nic), @@ -390,6 +402,12 @@ int aq_ring_rx_clean(struct aq_ring_s *self, AQ_CFG_RX_FRAME_MAX); page_ref_inc(buff_->rxdata.page); buff_->is_cleaned = 1; + + buff->is_ip_cso &= buff_->is_ip_cso; + buff->is_udp_cso &= buff_->is_udp_cso; + buff->is_tcp_cso &= buff_->is_tcp_cso; + buff->is_cso_err |= buff_->is_cso_err; + } while (!buff_->is_eop); } }