diff mbox

[RFT] 8139cp: properly support change of MTU values [v2]

Message ID 20121203204608.GA9815@electric-eye.fr.zoreil.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Francois Romieu Dec. 3, 2012, 8:46 p.m. UTC
David Miller <davem@davemloft.net> :
[...]
> I've applied this to net-next, if it triggers any problems we have
> some time to work it out before 3.8 is released.

I have bounced the messages to David Woodhouse since he authored the
last 8139cp changes in net-next and owns the hardware to notice
regressions.

My message of two days ago was wrong : it is not possible for the irq
handler to process a Tx event after the rings have been freed. Things
still look racy wrt netpoll though.

Any objection against the patch below ?

(I did not gotoize the dev == NULL test: it is really unlikely and
should go away).

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

David Woodhouse Dec. 4, 2012, 3:44 p.m. UTC | #1
On Mon, 2012-12-03 at 21:46 +0100, Francois Romieu wrote:
> David Miller <davem@davemloft.net> :
> [...]
> > I've applied this to net-next, if it triggers any problems we have
> > some time to work it out before 3.8 is released.
> 
> I have bounced the messages to David Woodhouse since he authored the
> last 8139cp changes in net-next and owns the hardware to notice
> regressions.

Thanks. 

This almost works. The patch itself is fine, but the device can't
receive packets larger than 2266 bytes (ping -s 2238). After that, I get
rx_fifo errors. I think the RX FIFO is only 2KiB on the 8139cp, isn't
it? So after that it's dependent on how fast it can shovel it out across
the PCI bus. Which is "not fast" in this case.

Transmit appears to be fine.
John Greene Dec. 4, 2012, 7:04 p.m. UTC | #2
On 12/04/2012 10:44 AM, David Woodhouse wrote:
> On Mon, 2012-12-03 at 21:46 +0100, Francois Romieu wrote:
>> David Miller <davem@davemloft.net> :
>> [...]
>>> I've applied this to net-next, if it triggers any problems we have
>>> some time to work it out before 3.8 is released.
>>
>> I have bounced the messages to David Woodhouse since he authored the
>> last 8139cp changes in net-next and owns the hardware to notice
>> regressions.
>
> Thanks.
>
> This almost works. The patch itself is fine, but the device can't
> receive packets larger than 2266 bytes (ping -s 2238). After that, I get
> rx_fifo errors. I think the RX FIFO is only 2KiB on the 8139cp, isn't
> it? So after that it's dependent on how fast it can shovel it out across
> the PCI bus. Which is "not fast" in this case.
>
> Transmit appears to be fine.
>
Checked the datasheet (admittedly old v1.5 12/6/2001): yes FIFOs are 2k 
on both Rx and Tx.  I need to check this on the emulator again, but it 
didn't fail with pings up to nearly 9000 bytes, apparently a difference 
of real vs. virtual hardware (perhaps an interesting science experiment 
to adjust MTU to what the underlying hardware does, but not today ;)

Still, this does fix reported problem that driver could be set to huge 
MTU erroneously, and now rejects really weird values as it should.

Thanks for the test, David.

Anything to add/subtract?

Francois: I noted your follow on patch, find merit in it as well.  I 
need to digest it more fully and expect it should be a follow up to this 
barring any other issues from me: appreciate your help also!
John Greene Dec. 5, 2012, 7:41 p.m. UTC | #3
On 12/03/2012 03:46 PM, Francois Romieu wrote:
> David Miller <davem@davemloft.net> :
> [...]
>> I've applied this to net-next, if it triggers any problems we have
>> some time to work it out before 3.8 is released.
>
> I have bounced the messages to David Woodhouse since he authored the
> last 8139cp changes in net-next and owns the hardware to notice
> regressions.
>
> My message of two days ago was wrong : it is not possible for the irq
> handler to process a Tx event after the rings have been freed. Things
> still look racy wrt netpoll though.
>
> Any objection against the patch below ?
>
> (I did not gotoize the dev == NULL test: it is really unlikely and
> should go away).
>
> diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
> index 0da3f5e..57cd542 100644
> --- a/drivers/net/ethernet/realtek/8139cp.c
> +++ b/drivers/net/ethernet/realtek/8139cp.c
> @@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   {
>   	struct net_device *dev = dev_instance;
>   	struct cp_private *cp;
> +	int handled = 0;
>   	u16 status;
>
>   	if (unlikely(dev == NULL))
>   		return IRQ_NONE;
>   	cp = netdev_priv(dev);
>
> +	spin_lock(&cp->lock);
> +
>   	status = cpr16(IntrStatus);
>   	if (!status || (status == 0xFFFF))
> -		return IRQ_NONE;
> +		goto out_unlock;
> +
> +	handled = 1;
>
>   	netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
>   		  status, cpr8(Cmd), cpr16(CpCmd));
>
>   	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
>
> -	spin_lock(&cp->lock);
> -
>   	/* close possible race's with dev_close */
>   	if (unlikely(!netif_running(dev))) {
>   		cpw16(IntrMask, 0);
> -		spin_unlock(&cp->lock);
> -		return IRQ_HANDLED;
> +		goto out_unlock;
>   	}
>
>   	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
> @@ -612,8 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   	if (status & LinkChg)
>   		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
>
> -	spin_unlock(&cp->lock);
> -
>   	if (status & PciErr) {
>   		u16 pci_status;
>
> @@ -625,7 +625,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   		/* TODO: reset hardware */
>   	}
>
> -	return IRQ_HANDLED;
> +out_unlock:
> +	spin_unlock(&cp->lock);
> +
> +	return IRQ_RETVAL(handled);
>   }
>
>   #ifdef CONFIG_NET_POLL_CONTROLLER
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
I think this is a good change, interesting it isn't in already or 
causing more issues on multi-processor boxes already. (perhaps it is?).

So do you think these patches need to go together? I could make a case 
either way.

Is this upstream yet?
David Woodhouse Dec. 6, 2012, 1:34 a.m. UTC | #4
On Tue, 2012-12-04 at 14:04 -0500, John Greene wrote:
> Still, this does fix reported problem that driver could be set to huge
> MTU erroneously, and now rejects really weird values as it should.

Yes, absolutely. As long as the caveat is understood, feel free to add
Tested-by: David Woodhouse <David.Woodhouse@intel.com>

I did look through the datasheet to see if there's anything we can do to
improve reception of large packets. We could try to reduce the Rx Fifo
threshold, which we currently set at 512 bytes... but it isn't going to
get us much further on this particular hardware. Might be nice to have
it tunable though.

There's a v1.6 datasheet at http://realtek.info/pdf/rtl8139cp.pdf btw.
John Greene Dec. 13, 2012, 7:56 p.m. UTC | #5
On 12/03/2012 03:46 PM, Francois Romieu wrote:
> David Miller <davem@davemloft.net> :
> [...]
>> I've applied this to net-next, if it triggers any problems we have
>> some time to work it out before 3.8 is released.
>
> I have bounced the messages to David Woodhouse since he authored the
> last 8139cp changes in net-next and owns the hardware to notice
> regressions.
>
> My message of two days ago was wrong : it is not possible for the irq
> handler to process a Tx event after the rings have been freed. Things
> still look racy wrt netpoll though.
>
> Any objection against the patch below ?
>
> (I did not gotoize the dev == NULL test: it is really unlikely and
> should go away).
>
> diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
> index 0da3f5e..57cd542 100644
> --- a/drivers/net/ethernet/realtek/8139cp.c
> +++ b/drivers/net/ethernet/realtek/8139cp.c
> @@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   {
>   	struct net_device *dev = dev_instance;
>   	struct cp_private *cp;
> +	int handled = 0;
>   	u16 status;
>
>   	if (unlikely(dev == NULL))
>   		return IRQ_NONE;
>   	cp = netdev_priv(dev);
>
> +	spin_lock(&cp->lock);
> +
>   	status = cpr16(IntrStatus);
>   	if (!status || (status == 0xFFFF))
> -		return IRQ_NONE;
> +		goto out_unlock;
> +
> +	handled = 1;
>
>   	netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
>   		  status, cpr8(Cmd), cpr16(CpCmd));
>
>   	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
>
> -	spin_lock(&cp->lock);
> -
>   	/* close possible race's with dev_close */
>   	if (unlikely(!netif_running(dev))) {
>   		cpw16(IntrMask, 0);
> -		spin_unlock(&cp->lock);
> -		return IRQ_HANDLED;
> +		goto out_unlock;
>   	}
>
>   	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
> @@ -612,8 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   	if (status & LinkChg)
>   		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
>
> -	spin_unlock(&cp->lock);
> -
>   	if (status & PciErr) {
>   		u16 pci_status;
>
> @@ -625,7 +625,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
>   		/* TODO: reset hardware */
>   	}
>
> -	return IRQ_HANDLED;
> +out_unlock:
> +	spin_unlock(&cp->lock);
> +
> +	return IRQ_RETVAL(handled);
>   }
>
>   #ifdef CONFIG_NET_POLL_CONTROLLER
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Francois,

Have incorporated this and test it on virtual hardware with on top of
  cb64edb6b89491edfdbae52ba7db9a8b8391d339 (my original work now 
upstream).  I plan to submit your work herein upstream as well, with 
attribution to you, if that's ok?
Francois Romieu Dec. 13, 2012, 10:36 p.m. UTC | #6
John Greene <jogreene@redhat.com> :
[...]
> Have incorporated this and test it on virtual hardware with on top of
> cb64edb6b89491edfdbae52ba7db9a8b8391d339 (my original work now
> upstream).  I plan to submit your work herein upstream as well, with
> attribution to you, if that's ok?

Sure, go ahead.

I have a nasty 8110s (old netgear) bug to keep me busy.
diff mbox

Patch

diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 0da3f5e..57cd542 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -577,28 +577,30 @@  static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct cp_private *cp;
+	int handled = 0;
 	u16 status;
 
 	if (unlikely(dev == NULL))
 		return IRQ_NONE;
 	cp = netdev_priv(dev);
 
+	spin_lock(&cp->lock);
+
 	status = cpr16(IntrStatus);
 	if (!status || (status == 0xFFFF))
-		return IRQ_NONE;
+		goto out_unlock;
+
+	handled = 1;
 
 	netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
 		  status, cpr8(Cmd), cpr16(CpCmd));
 
 	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
 
-	spin_lock(&cp->lock);
-
 	/* close possible race's with dev_close */
 	if (unlikely(!netif_running(dev))) {
 		cpw16(IntrMask, 0);
-		spin_unlock(&cp->lock);
-		return IRQ_HANDLED;
+		goto out_unlock;
 	}
 
 	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
@@ -612,8 +614,6 @@  static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 	if (status & LinkChg)
 		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
-	spin_unlock(&cp->lock);
-
 	if (status & PciErr) {
 		u16 pci_status;
 
@@ -625,7 +625,10 @@  static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 		/* TODO: reset hardware */
 	}
 
-	return IRQ_HANDLED;
+out_unlock:
+	spin_unlock(&cp->lock);
+
+	return IRQ_RETVAL(handled);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER