Re: [patch sungem] improved locking
From: Eric Lemoine <hidden>
Date: 2006-11-29 10:56:32
On 11/28/06, David Miller [off-list ref] wrote:
From: "Eric Lemoine" <redacted> Date: Tue, 14 Nov 2006 22:54:40 +0100quoted
On 11/14/06, David Miller [off-list ref] wrote:quoted
From: "Eric Lemoine" <redacted> Date: Tue, 14 Nov 2006 08:28:42 +0100quoted
because it makes it explicit that only bits 0 through 6 are taken into account when writing the IACK register.The phrase "bits 0 through 6" doesn't make any sense when bit 3 DOES NOT EXIST in the hardware, it's reserved, it's not there, so including it only confuses people and obfuscates the code. Please use the explicit bit mask composed of existing macros, which not only makes sure that the mask has meaning, but it also makes sure that reserved and non-existing bits are never referenced.Patch attached. Remember, the GEM_INTERRUPT_LOCKLESS isn't there to stay. It's currently there because I'm not sure the lockless implementation of gem_interrupt() will work with poll_net_controller. Thanks, Signed-off-by: Eric Lemoine <redacted>This looks mostly fine. I was thinking about the lockless stuff, and I wonder if there is a clever way you can get it back down to one PIO on the GREG_STAT register. I think you'd need to have the ->poll() clear gp->status, then do a smp_wb(), right before it re-enables interrupts. Then in the interrupt handler, you need to find a way to safely OR-in any unset bits in gp->status in a race-free manner.
I don't understand why we'd need all this.
I think the following code for gem_interrupt should do the trick:
static irqreturn_t gem_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct gem *gp = dev->priv;
unsigned int handled = 1;
if (!gp->running)
goto out;
if (netif_rx_schedule_prep(dev)) {
u32 gem_status = gem_read_status(gp);
gem_disable_ints();
if (unlikely(!gem_status))
handled = 0;
if (gem_irq_sync(gp)) {
netif_poll_enable(dev);
goto out;
}
gp->status = gem_status;
__netif_rx_schedule(dev);
}
out:
return IRQ_RETVAL(handled);
}
The important thing is: we __netif_rx_schedule even if gem_status is 0
(shared irq case) because we don't want to miss events should the
following scenario occur:
CPU0 CPU1
gem interrupt
prepare rx schedule
gem_interrupt
rx is
already scheduled
shared irq -> (we can miss NIC events
if we don't __netif_rx_schedule before
returning)
Thanks,
--
Eric