Message ID | 22d742b4e7d11ff48e8c40e39db3c776e495abe2.1677981671.git.geoff@infradead.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net/ps3_gelic_net: DMA related fixes | expand |
On Sun, 2023-03-05 at 02:08 +0000, Geoff Levand wrote: > The Gelic Ethernet device needs to have the RX sk_buffs aligned to > GELIC_NET_RXBUF_ALIGN, and also the length of the RX sk_buffs must > be a multiple of GELIC_NET_RXBUF_ALIGN. > > The current Gelic Ethernet driver was not allocating sk_buffs large > enough to allow for this alignment. > > Also, correct the maximum and minimum MTU sizes, and add a new > preprocessor macro for the maximum frame size, GELIC_NET_MAX_FRAME. > > Fixes various randomly occurring runtime network errors. > > Fixes: 02c1889166b4 ("ps3: gigabit ethernet driver for PS3, take3") > Signed-off-by: Geoff Levand <geoff@infradead.org> > --- > drivers/net/ethernet/toshiba/ps3_gelic_net.c | 10 ++++++---- > drivers/net/ethernet/toshiba/ps3_gelic_net.h | 5 +++-- > 2 files changed, 9 insertions(+), 6 deletions(-) > > diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c > index cf8de8a7a8a1..b0ebe0e603b4 100644 > --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c > +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c > @@ -375,11 +375,13 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, > if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) > dev_info(ctodev(card), "%s: ERROR status\n", __func__); > /* we need to round up the buffer size to a multiple of 128 */ > - bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); > + bufsize = (GELIC_NET_MAX_FRAME + GELIC_NET_RXBUF_ALIGN - 1) & > + (~(GELIC_NET_RXBUF_ALIGN - 1)); Why did you stop using ALIGN? What you coded looks exactly like what the code for ALIGN does. From what I can tell you just need to replace GELIC_NET_MAX_MTU with GELIC_NET_MAX_FRAME. > > /* and we need to have it 128 byte aligned, therefore we allocate a > * bit more */ > - descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); > + descr->skb = netdev_alloc_skb(*card->netdev, bufsize + > + GELIC_NET_RXBUF_ALIGN - 1); This wrapping doesn't look right to me. Also why add the align value again here? I would think that it being added above should have taken care of what you needed. Are you adding any data beyond the end of what is DMAed into the frame? > if (!descr->skb) { > descr->buf_addr = 0; /* tell DMAC don't touch memory */ > return -ENOMEM; > @@ -397,7 +399,7 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, > /* io-mmu-map the skb */ > descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), > descr->skb->data, > - GELIC_NET_MAX_MTU, > + GELIC_NET_MAX_FRAME, > DMA_FROM_DEVICE)); Rather than using the define GELIC_NET_MAX_FRAME, why not just use bufsize since that is what you actually have allocated for receive? > if (!descr->buf_addr) { > dev_kfree_skb_any(descr->skb); > @@ -915,7 +917,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, > data_error = be32_to_cpu(descr->data_error); > /* unmap skb buffer */ > dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), > - GELIC_NET_MAX_MTU, > + GELIC_NET_MAX_FRAME, > DMA_FROM_DEVICE); I suppose my suggestion above would cause a problem here since you would need to also define buffer size here. However since it looks like you are adding a define below anyway maybe you should just look at adding a new RX_BUFSZ define and just drop bufsize completely. > > skb_put(skb, be32_to_cpu(descr->valid_size)? > diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h > index 68f324ed4eaf..0d98defb011e 100644 > --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h > +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h > @@ -19,8 +19,9 @@ > #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ > #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ > > -#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN > -#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN > +#define GELIC_NET_MAX_FRAME 2312 > +#define GELIC_NET_MAX_MTU 2294 > +#define GELIC_NET_MIN_MTU 64 > #define GELIC_NET_RXBUF_ALIGN 128 > #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ > #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ Since you are adding defines why not just add: #define GELIC_NET_RX_BUFSZ \ ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN)
Hi, On 3/6/23 07:54, Alexander H Duyck wrote: > On Sun, 2023-03-05 at 02:08 +0000, Geoff Levand wrote: >> The Gelic Ethernet device needs to have the RX sk_buffs aligned to >> GELIC_NET_RXBUF_ALIGN, and also the length of the RX sk_buffs must >> be a multiple of GELIC_NET_RXBUF_ALIGN. >> >> The current Gelic Ethernet driver was not allocating sk_buffs large >> enough to allow for this alignment. >> >> Also, correct the maximum and minimum MTU sizes, and add a new >> preprocessor macro for the maximum frame size, GELIC_NET_MAX_FRAME. >> >> Fixes various randomly occurring runtime network errors. >> >> Fixes: 02c1889166b4 ("ps3: gigabit ethernet driver for PS3, take3") >> Signed-off-by: Geoff Levand <geoff@infradead.org> >> --- >> drivers/net/ethernet/toshiba/ps3_gelic_net.c | 10 ++++++---- >> drivers/net/ethernet/toshiba/ps3_gelic_net.h | 5 +++-- >> 2 files changed, 9 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c >> index cf8de8a7a8a1..b0ebe0e603b4 100644 >> --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c >> +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c >> @@ -375,11 +375,13 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, >> if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) >> dev_info(ctodev(card), "%s: ERROR status\n", __func__); >> /* we need to round up the buffer size to a multiple of 128 */ >> - bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); >> + bufsize = (GELIC_NET_MAX_FRAME + GELIC_NET_RXBUF_ALIGN - 1) & >> + (~(GELIC_NET_RXBUF_ALIGN - 1)); > > Why did you stop using ALIGN? What you coded looks exactly like what > the code for ALIGN does. From what I can tell you just need to replace > GELIC_NET_MAX_MTU with GELIC_NET_MAX_FRAME. OK, I'll use ALIGN for the next patch set. >> /* and we need to have it 128 byte aligned, therefore we allocate a >> * bit more */ >> - descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); >> + descr->skb = netdev_alloc_skb(*card->netdev, bufsize + >> + GELIC_NET_RXBUF_ALIGN - 1); > > This wrapping doesn't look right to me. Also why add the align value > again here? I would think that it being added above should have taken > care of what you needed. Are you adding any data beyond the end of what > is DMAed into the frame? This is just a straight copy of what is done in the spider net driver. As I mentioned in the comment of this patch, the DMA buffer must be a multiple of GELIC_NET_RXBUF_ALIGN, and that is what that extra 'GELIC_NET_RXBUF_ALIGN - 1' is for. >> if (!descr->skb) { >> descr->buf_addr = 0; /* tell DMAC don't touch memory */ >> return -ENOMEM; >> @@ -397,7 +399,7 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, >> /* io-mmu-map the skb */ >> descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), >> descr->skb->data, >> - GELIC_NET_MAX_MTU, >> + GELIC_NET_MAX_FRAME, >> DMA_FROM_DEVICE)); > > Rather than using the define GELIC_NET_MAX_FRAME, why not just use > bufsize since that is what you actually have allocated for receive? Again, this is a straight copy of what is done in the spider net driver. It does seem like using bufsize would be better, so I'll change that. >> if (!descr->buf_addr) { >> dev_kfree_skb_any(descr->skb); >> @@ -915,7 +917,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, >> data_error = be32_to_cpu(descr->data_error); >> /* unmap skb buffer */ >> dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), >> - GELIC_NET_MAX_MTU, >> + GELIC_NET_MAX_FRAME, >> DMA_FROM_DEVICE); > > I suppose my suggestion above would cause a problem here since you > would need to also define buffer size here. However since it looks like > you are adding a define below anyway maybe you should just look at > adding a new RX_BUFSZ define and just drop bufsize completely. I think making bufsize a static const would be better, since it would avoid using the pre-processor. >> skb_put(skb, be32_to_cpu(descr->valid_size)? >> diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h >> index 68f324ed4eaf..0d98defb011e 100644 >> --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h >> +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h >> @@ -19,8 +19,9 @@ >> #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ >> #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ >> >> -#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN >> -#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN >> +#define GELIC_NET_MAX_FRAME 2312 >> +#define GELIC_NET_MAX_MTU 2294 >> +#define GELIC_NET_MIN_MTU 64 >> #define GELIC_NET_RXBUF_ALIGN 128 >> #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ >> #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ > > Since you are adding defines why not just add: > #define GELIC_NET_RX_BUFSZ \ > ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) Thanks for the review. -Geoff
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index cf8de8a7a8a1..b0ebe0e603b4 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -375,11 +375,13 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) dev_info(ctodev(card), "%s: ERROR status\n", __func__); /* we need to round up the buffer size to a multiple of 128 */ - bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); + bufsize = (GELIC_NET_MAX_FRAME + GELIC_NET_RXBUF_ALIGN - 1) & + (~(GELIC_NET_RXBUF_ALIGN - 1)); /* and we need to have it 128 byte aligned, therefore we allocate a * bit more */ - descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); + descr->skb = netdev_alloc_skb(*card->netdev, bufsize + + GELIC_NET_RXBUF_ALIGN - 1); if (!descr->skb) { descr->buf_addr = 0; /* tell DMAC don't touch memory */ return -ENOMEM; @@ -397,7 +399,7 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, /* io-mmu-map the skb */ descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), descr->skb->data, - GELIC_NET_MAX_MTU, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE)); if (!descr->buf_addr) { dev_kfree_skb_any(descr->skb); @@ -915,7 +917,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, data_error = be32_to_cpu(descr->data_error); /* unmap skb buffer */ dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), - GELIC_NET_MAX_MTU, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE); skb_put(skb, be32_to_cpu(descr->valid_size)? diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h index 68f324ed4eaf..0d98defb011e 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h @@ -19,8 +19,9 @@ #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ -#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN -#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN +#define GELIC_NET_MAX_FRAME 2312 +#define GELIC_NET_MAX_MTU 2294 +#define GELIC_NET_MIN_MTU 64 #define GELIC_NET_RXBUF_ALIGN 128 #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ
The Gelic Ethernet device needs to have the RX sk_buffs aligned to GELIC_NET_RXBUF_ALIGN, and also the length of the RX sk_buffs must be a multiple of GELIC_NET_RXBUF_ALIGN. The current Gelic Ethernet driver was not allocating sk_buffs large enough to allow for this alignment. Also, correct the maximum and minimum MTU sizes, and add a new preprocessor macro for the maximum frame size, GELIC_NET_MAX_FRAME. Fixes various randomly occurring runtime network errors. Fixes: 02c1889166b4 ("ps3: gigabit ethernet driver for PS3, take3") Signed-off-by: Geoff Levand <geoff@infradead.org> --- drivers/net/ethernet/toshiba/ps3_gelic_net.c | 10 ++++++---- drivers/net/ethernet/toshiba/ps3_gelic_net.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-)