On Mon, Dec 07, 2020 at 10:28:59AM +0100, Tobias Heider wrote:
> Hi,
>
> In iwm_rx_pkt() the calculation of "remain" seems to be wrong if
> there are three or more MPDUs in one packet.
> "remain" is initialized with the output buffer size.
> Each time an MPDU is found in the packet remain is reduced
> by the offset of the MPDU in the receive buffer, which is only
> correct for the first MPDU in the packet.
> This causes spurious input errors.
>
> We can fix this by removing the "remain" variable.
> The variable "offset" always points to the current position in the
> receive buffer and the maximum size of the receive buffer is fixed.
> Thus offset can be used for the caculation of maxlen.
>
> ok?
Please credit Christian Ehrhardt who did all the hard work in
tracking this down :)
ok!
>
> Index: if_iwm.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.315
> diff -u -p -r1.315 if_iwm.c
> --- if_iwm.c 11 Oct 2020 07:05:28 -0000 1.315
> +++ if_iwm.c 7 Dec 2020 09:02:44 -0000
> @@ -8494,7 +8494,6 @@ iwm_rx_pkt(struct iwm_softc *sc, struct
> uint32_t offset = 0, nextoff = 0, nmpdu = 0, len;
> struct mbuf *m0, *m;
> const size_t minsz = sizeof(pkt->len_n_flags) + sizeof(pkt->hdr);
> - size_t remain = IWM_RBUF_SIZE;
> int qid, idx, code, handled = 1;
>
> bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
> @@ -8531,7 +8530,7 @@ iwm_rx_pkt(struct iwm_softc *sc, struct
> break;
>
> case IWM_REPLY_RX_MPDU_CMD: {
> - size_t maxlen = remain - minsz;
> + size_t maxlen = IWM_RBUF_SIZE - offset - minsz;
> nextoff = offset +
> roundup(len, IWM_FH_RSCSR_FRAME_ALIGN);
> nextpkt = (struct iwm_rx_packet *)
> @@ -8569,11 +8568,6 @@ iwm_rx_pkt(struct iwm_softc *sc, struct
> iwm_rx_mpdu(sc, m, pkt->data,
> maxlen, ml);
> }
> -
> - if (offset + minsz < remain)
> - remain -= offset;
> - else
> - remain = minsz;
> break;
> }
>
>
>