2006-05-23 21:52:28

by Daniel J Blueman

[permalink] [raw]
Subject: Re: sky2 large MTU problems...

Hi Stephen,

I can confirm that I am unable to reproduce any of the problems I was
seeing - it works as expected all the way up to the sky2 maximum MTU
size of 9000. Fantastic!

Thanks again,
Daniel

On 22/05/06, Stephen Hemminger <[email protected]> wrote:
> Try this, not completely baked yet though..
>
> --- sky2.orig/drivers/net/sky2.c 2006-05-22 10:23:51.000000000 -0700
> +++ sky2/drivers/net/sky2.c 2006-05-22 11:30:50.000000000 -0700
> @@ -636,8 +636,10 @@
> TX_BACK_OFF_LIM(TX_BOF_LIM_DEF));
>
> /* serial mode register */
> - reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
> - GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
> + reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |IPG_DATA_VAL(IPG_DATA_DEF);
> +#ifdef SKY2_VLAN_TAG_USED
> + reg |= GM_SMOD_VLAN_ENA;
> +#endif
>
> if (hw->dev[port]->mtu > ETH_DATA_LEN)
> reg |= GM_SMOD_JUMBO_ENA;
> @@ -979,6 +981,7 @@
> struct sky2_hw *hw = sky2->hw;
> unsigned rxq = rxqaddr[sky2->port];
> int i;
> + unsigned thresh;
>
> sky2->rx_put = sky2->rx_next = 0;
> sky2_qset(hw, rxq);
> @@ -1003,9 +1006,22 @@
> sky2_rx_add(sky2, re->mapaddr);
> }
>
> - /* Truncate oversize frames */
> - sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8);
> - sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
> +
> + /*
> + * The receiver hangs gets stuck if it receives frames larger than the
> + * packet buffer. As a workaround, truncate oversize frames, but
> + * truncate register is to 9 bits, so if you do jumbo frames
> + * you better get the MTU right.
> + */
> + thresh = (ALIGN(sky2->netdev->mtu + ETH_HLEN, 4) - 8)/4;
> +
> + if (thresh > 0x1ff)
> + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
> + else {
> + sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
> + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
> + }
> +
>
> /* Tell chip about available buffers */
> sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
> @@ -1754,7 +1770,7 @@
> */
> static inline unsigned sky2_buf_size(int mtu)
> {
> - return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
> + return ALIGN(mtu + ETH_HLEN, 8) + 8;
> }
>
> static int sky2_change_mtu(struct net_device *dev, int new_mtu)
> @@ -1792,8 +1808,10 @@
>
> dev->mtu = new_mtu;
> sky2->rx_bufsize = sky2_buf_size(new_mtu);
> - mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |
> - GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
> + mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |IPG_DATA_VAL(IPG_DATA_DEF);
> +#ifdef SKY2_VLAN_TAG_USED
> + mode |= GM_SMOD_VLAN_ENA;
> +#endif
>
> if (dev->mtu > ETH_DATA_LEN)
> mode |= GM_SMOD_JUMBO_ENA;
>
--
Daniel J Blueman