Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f38f1ee8 authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by David S. Miller
Browse files

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: 018423e9 ("net: ethernet: aquantia: Add ring support code")
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31bafc49
Loading
Loading
Loading
Loading
+31 −13
Original line number Diff line number Diff line
@@ -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;
			buff_ = buff;
			do {
				next_ = buff_->next,
			     buff_ = &self->buff_ring[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);
			}
		}