summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
diff options
context:
space:
mode:
authorDmitry Bogdanov <dmitry.bogdanov@aquantia.com>2019-05-25 09:58:01 +0000
committerDavid S. Miller <davem@davemloft.net>2019-05-27 10:24:14 -0700
commitf38f1ee8aeb2c19f65fc29de49bed231a868198c (patch)
treef12925d18c9a895474272e1fe9c5f4f3b958d56f /drivers/net/ethernet/aquantia/atlantic/aq_ring.c
parent31bafc49a7736989e4c2d9f7280002c66536e590 (diff)
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 <igor.russkikh@aquantia.com> Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/aquantia/atlantic/aq_ring.c')
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ring.c44
1 files changed, 31 insertions, 13 deletions
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);
}
}