linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Marvell MV64360 interrupt question
@ 2005-09-09 17:31 Walter L. Wimer III
  2005-09-09 19:09 ` Walter L. Wimer III
  2005-09-09 19:27 ` Dale Farnsworth
  0 siblings, 2 replies; 9+ messages in thread
From: Walter L. Wimer III @ 2005-09-09 17:31 UTC (permalink / raw)
  To: Linux PPC Embedded list


Hi All,

I'm looking at arch/ppc/syslib/mv64360_pic.c in the 2.6.13 kernel and I
see the following code:

    int
    mv64360_get_irq(struct pt_regs *regs)
    {
        .
        .
        .
        if (irq == -1) {
            irq = mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_HI);
            irq = __ilog2((irq & 0x1f0003f7) & ppc_cached_irq_mask[1]);

            if (irq == -1)
                irq = -2; /* bogus interrupt, should never happen */
            else {
                if ((irq >= 24) && (irq < MV64x60_IRQ_DOORBELL)) {
                    irq_gpp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
                    irq_gpp = __ilog2(irq_gpp & ppc_cached_irq_mask[2]);

                    if (irq_gpp == -1)
                        irq = -2;
                    else {
                        irq = irq_gpp + 64;
                        mv64x60_write(&bh,
                                      MV64x60_GPP_INTR_CAUSE,
                                      (1 << (irq - 64)));
                    }
                }
                else
		    irq += 32;
            }
        }

        (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
        .
        .
        .
    }

Does anybody know what the last mv64x60_read() is intended to do?  It
*looks* like it's clearing/acknowledging the interrupt, but I don't see
anything in the Marvell documentation that suggests that *reading* the
interrupt cause register has such an effect.  From my reading, the
documentation says that you should write a '0' into the appropriate bit
position to clear the interrupt.

Hmmm...  There's an mv64x60_write() a little earlier in the code...  Is
the "extra" mv64x60_read() here to enforce ordering?  If so, should it
be moved inside the "if" statement so that it's only executed when
actually necessary?

And what about locking?  The mv64x60_xxxx() functions are protected by a
spinlock, but if we're trying to enforce ordering, shouldn't we hold the
lock during the entire write+read operation, rather than dropping and
reacquiring the lock in between?


At the moment, I'm not running into any actual problems here; this just
caught my eye and I started wondering about it.

BTW, the reason I'm looking at this code is that the board I'm working
on has a cascaded interrupt controller (implemented in an FPGA) feeding
into the MV64360 interrupt controller.  I'm thinking about adding a
cascade mechanism to mv64360_pic.c similar to the one in the OpenPIC
code (i.e. like the openpic_hookup_cascade() function).  Any opinions on
whether this is a good idea or a bad one?



Thanks!!!

Walt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 17:31 Marvell MV64360 interrupt question Walter L. Wimer III
@ 2005-09-09 19:09 ` Walter L. Wimer III
  2005-09-12 12:56   ` Brian Waite
  2005-09-09 19:27 ` Dale Farnsworth
  1 sibling, 1 reply; 9+ messages in thread
From: Walter L. Wimer III @ 2005-09-09 19:09 UTC (permalink / raw)
  To: Linux PPC Embedded list


Thinking about this some more, I think the cascade mechanism I suggested
earlier is backwards.  Architecturally, I think it makes more sense to
define a platform-specific function like boardXYZ_get_irq() in
boardXYZ_setup.c that knows all of the idiosyncrasies of the board and
calls whatever standard PIC libraries it needs in order to do the right
thing.  Then we set ppc_md.get_irq = boardXYZ_get_irq;

I looked around, and lo and behold, the Radstone PPC7D already "stole"
my idea.  :-)  :-)

    static int ppc7d_get_irq(struct pt_regs *regs)
    {
        int irq;

        irq = mv64360_get_irq(regs);
        if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
            irq = i8259_irq(regs);
        return irq;
    }


Any comments on the "extra" mv64x60_read() call in mv64360_get_irq() are
still welcome.



Thanks!

Walt



On Fri, 2005-09-09 at 13:31 -0400, Walter L. Wimer III wrote:
> BTW, the reason I'm looking at this code is that the board I'm working
> on has a cascaded interrupt controller (implemented in an FPGA) feeding
> into the MV64360 interrupt controller.  I'm thinking about adding a
> cascade mechanism to mv64360_pic.c similar to the one in the OpenPIC
> code (i.e. like the openpic_hookup_cascade() function).  Any opinions on
> whether this is a good idea or a bad one?
> 
> 
> 
> Thanks!!!
> 
> Walt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 17:31 Marvell MV64360 interrupt question Walter L. Wimer III
  2005-09-09 19:09 ` Walter L. Wimer III
@ 2005-09-09 19:27 ` Dale Farnsworth
  2005-09-09 19:52   ` Walter L. Wimer III
  2005-09-09 20:20   ` Walter L. Wimer III
  1 sibling, 2 replies; 9+ messages in thread
From: Dale Farnsworth @ 2005-09-09 19:27 UTC (permalink / raw)
  To: linuxppc-embedded

On Fri, Sep 09, 2005 at 05:31:32PM +0000, Walter L. Wimer III wrote:
> I'm looking at arch/ppc/syslib/mv64360_pic.c in the 2.6.13 kernel and I
> see the following code:
> 
>     int
>     mv64360_get_irq(struct pt_regs *regs)
>     {
>         .
>         .
>         .
>         if (irq == -1) {
>             irq = mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_HI);
>             irq = __ilog2((irq & 0x1f0003f7) & ppc_cached_irq_mask[1]);
> 
>             if (irq == -1)
>                 irq = -2; /* bogus interrupt, should never happen */
>             else {
>                 if ((irq >= 24) && (irq < MV64x60_IRQ_DOORBELL)) {
>                     irq_gpp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
>                     irq_gpp = __ilog2(irq_gpp & ppc_cached_irq_mask[2]);
> 
>                     if (irq_gpp == -1)
>                         irq = -2;
>                     else {
>                         irq = irq_gpp + 64;
>                         mv64x60_write(&bh,
>                                       MV64x60_GPP_INTR_CAUSE,
>                                       (1 << (irq - 64)));

You dropped a ~ on the above line.  It confused me for a bit.

>                     }
>                 }
>                 else
> 		    irq += 32;
>             }
>         }
> 
>         (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
>         .
>         .
>         .
>     }
> 
> Does anybody know what the last mv64x60_read() is intended to do?  It
> *looks* like it's clearing/acknowledging the interrupt, but I don't see
> anything in the Marvell documentation that suggests that *reading* the
> interrupt cause register has such an effect.  From my reading, the
> documentation says that you should write a '0' into the appropriate bit
> position to clear the interrupt.
> 
> Hmmm...  There's an mv64x60_write() a little earlier in the code...  Is
> the "extra" mv64x60_read() here to enforce ordering?  If so, should it
> be moved inside the "if" statement so that it's only executed when
> actually necessary?

Yes.  It's there to make sure that the clearing of the GPP interrupt
is seen by the hardware and takes effect before we return from the function.

> And what about locking?  The mv64x60_xxxx() functions are protected by a
> spinlock, but if we're trying to enforce ordering, shouldn't we hold the
> lock during the entire write+read operation, rather than dropping and
> reacquiring the lock in between?

No additional locking is necessary.  In fact, it seems to me that the 32-bit
register reads and writes are already atomic and all of the locking using
mv64x60_lock is superfluous.

> At the moment, I'm not running into any actual problems here; this just
> caught my eye and I started wondering about it.
> 
> BTW, the reason I'm looking at this code is that the board I'm working
> on has a cascaded interrupt controller (implemented in an FPGA) feeding
> into the MV64360 interrupt controller.  I'm thinking about adding a
> cascade mechanism to mv64360_pic.c similar to the one in the OpenPIC
> code (i.e. like the openpic_hookup_cascade() function).  Any opinions on
> whether this is a good idea or a bad one?

Sounds reasonable to me.

-Dale

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 19:27 ` Dale Farnsworth
@ 2005-09-09 19:52   ` Walter L. Wimer III
  2005-09-09 20:20   ` Walter L. Wimer III
  1 sibling, 0 replies; 9+ messages in thread
From: Walter L. Wimer III @ 2005-09-09 19:52 UTC (permalink / raw)
  To: Linux PPC Embedded list


Thanks for your response, Dale!


Walt



On Fri, 2005-09-09 at 12:27 -0700, Dale Farnsworth wrote:
> On Fri, Sep 09, 2005 at 05:31:32PM +0000, Walter L. Wimer III wrote:
> >                         mv64x60_write(&bh,
> >                                       MV64x60_GPP_INTR_CAUSE,
> >                                       (1 << (irq - 64)));
> 
> You dropped a ~ on the above line.  It confused me for a bit.
> 

Ooops!  Sorry about that!!!  Yikes!


> > Hmmm...  There's an mv64x60_write() a little earlier in the code...  Is
> > the "extra" mv64x60_read() here to enforce ordering?  If so, should it
> > be moved inside the "if" statement so that it's only executed when
> > actually necessary?
> 
> Yes.  It's there to make sure that the clearing of the GPP interrupt
> is seen by the hardware and takes effect before we return from the function.
> 
> > And what about locking?  The mv64x60_xxxx() functions are protected by a
> > spinlock, but if we're trying to enforce ordering, shouldn't we hold the
> > lock during the entire write+read operation, rather than dropping and
> > reacquiring the lock in between?
> 
> No additional locking is necessary.  In fact, it seems to me that the 32-bit
> register reads and writes are already atomic and all of the locking using
> mv64x60_lock is superfluous.

I wondered about that, too....

> 
> -Dale
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 19:27 ` Dale Farnsworth
  2005-09-09 19:52   ` Walter L. Wimer III
@ 2005-09-09 20:20   ` Walter L. Wimer III
  2005-09-09 20:49     ` Dale Farnsworth
  1 sibling, 1 reply; 9+ messages in thread
From: Walter L. Wimer III @ 2005-09-09 20:20 UTC (permalink / raw)
  To: Linux PPC Embedded list

On Fri, 2005-09-09 at 12:27 -0700, Dale Farnsworth wrote:
> 
> No additional locking is necessary.  In fact, it seems to me that the 32-bit
> register reads and writes are already atomic and all of the locking using
> mv64x60_lock is superfluous.

Ah ha.  mv64x60.h also defines an mv64x60_modify() function that isn't
intrinsically atomic, so it needs the spinlock.  That in turn requires
mv64x60_read() and mv64x60_write() to play along too.

At least in the general case....



Walt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 20:20   ` Walter L. Wimer III
@ 2005-09-09 20:49     ` Dale Farnsworth
  2005-09-09 21:18       ` Mark A. Greer
  0 siblings, 1 reply; 9+ messages in thread
From: Dale Farnsworth @ 2005-09-09 20:49 UTC (permalink / raw)
  To: linuxppc-embedded

On Fri, Sep 09, 2005 at 08:20:20PM +0000, Walter L. Wimer III wrote:
> On Fri, 2005-09-09 at 12:27 -0700, Dale Farnsworth wrote:
> > 
> > No additional locking is necessary.  In fact, it seems to me that the 32-bit
> > register reads and writes are already atomic and all of the locking using
> > mv64x60_lock is superfluous.
> 
> Ah ha.  mv64x60.h also defines an mv64x60_modify() function that isn't
> intrinsically atomic, so it needs the spinlock.  That in turn requires
> mv64x60_read() and mv64x60_write() to play along too.

Yes, the lock is needed for mv64x60_modify(), mv64x60_write().  I still
don't think it's needed for mv64x60_read().

-Dale

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 20:49     ` Dale Farnsworth
@ 2005-09-09 21:18       ` Mark A. Greer
  2005-09-12 13:05         ` Brian Waite
  0 siblings, 1 reply; 9+ messages in thread
From: Mark A. Greer @ 2005-09-09 21:18 UTC (permalink / raw)
  To: Dale Farnsworth; +Cc: linuxppc-embedded

On Fri, Sep 09, 2005 at 01:49:55PM -0700, Dale Farnsworth wrote:
> On Fri, Sep 09, 2005 at 08:20:20PM +0000, Walter L. Wimer III wrote:
> > On Fri, 2005-09-09 at 12:27 -0700, Dale Farnsworth wrote:
> > > 
> > > No additional locking is necessary.  In fact, it seems to me that the 32-bit
> > > register reads and writes are already atomic and all of the locking using
> > > mv64x60_lock is superfluous.
> > 
> > Ah ha.  mv64x60.h also defines an mv64x60_modify() function that isn't
> > intrinsically atomic, so it needs the spinlock.  That in turn requires
> > mv64x60_read() and mv64x60_write() to play along too.
> 
> Yes, the lock is needed for mv64x60_modify(), mv64x60_write().  I still
> don't think it's needed for mv64x60_read().

IMHO, the mv64x60_read/write/modify routines should be deleted and the
locking + I/O done explicitly.  That makes it more obvious, more
efficient in places where there are multiple writes, etc. in a row (not
as much grabbing/releasing of the spinlock), and is the preferred way to do
things in linux.

A few times now, I almost started to do that...looked at it and went off
to do something else.  :)  Yes, I'm lazy.  Yes, I should do it.
Eventually, I will (however, if you want to, I won't complain ;).

Mark

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 19:09 ` Walter L. Wimer III
@ 2005-09-12 12:56   ` Brian Waite
  0 siblings, 0 replies; 9+ messages in thread
From: Brian Waite @ 2005-09-12 12:56 UTC (permalink / raw)
  To: linuxppc-embedded

On Friday 09 September 2005 3:09 pm, Walter L. Wimer III wrote:
> Thinking about this some more, I think the cascade mechanism I suggested
> earlier is backwards.  Architecturally, I think it makes more sense to
> define a platform-specific function like boardXYZ_get_irq() in
> boardXYZ_setup.c that knows all of the idiosyncrasies of the board and
> calls whatever standard PIC libraries it needs in order to do the right
> thing.  Then we set ppc_md.get_irq = boardXYZ_get_irq;
>
> I looked around, and lo and behold, the Radstone PPC7D already "stole"
> my idea.  :-)  :-)
>
>
Yes, the syslib case in the general case. You can easily override the 
get_irq() routine for your own platform to match a priority scheme you 
desire. 

Thanks
Brian

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Marvell MV64360 interrupt question
  2005-09-09 21:18       ` Mark A. Greer
@ 2005-09-12 13:05         ` Brian Waite
  0 siblings, 0 replies; 9+ messages in thread
From: Brian Waite @ 2005-09-12 13:05 UTC (permalink / raw)
  To: linuxppc-embedded

On Friday 09 September 2005 5:18 pm, Mark A. Greer wrote:
> On Fri, Sep 09, 2005 at 01:49:55PM -0700, Dale Farnsworth wrote:
> > On Fri, Sep 09, 2005 at 08:20:20PM +0000, Walter L. Wimer III wrote:
> > > On Fri, 2005-09-09 at 12:27 -0700, Dale Farnsworth wrote:
> > > > No additional locking is necessary.  In fact, it seems to me that the
> > > > 32-bit register reads and writes are already atomic and all of the
> > > > locking using mv64x60_lock is superfluous.
Unless somthing has changed, on the get_irq case, the interrupts are only 
handled by CPU0. At least that is the way all the platforms have handled it 
in the past. I'd be wary of distributing across other cpus until you really 
look at the enet and mpsc drivers. I don't know of any races off the top of 
my head, but this code was tested and developed with boards only handling 
IRQs on one processor.
> > >
> > > Ah ha.  mv64x60.h also defines an mv64x60_modify() function that isn't
> > > intrinsically atomic, so it needs the spinlock.  That in turn requires
> > > mv64x60_read() and mv64x60_write() to play along too.

> >
> > Yes, the lock is needed for mv64x60_modify(), mv64x60_write().  I still
> > don't think it's needed for mv64x60_read().
>
> IMHO, the mv64x60_read/write/modify routines should be deleted and the
> locking + I/O done explicitly.  That makes it more obvious, more
> efficient in places where there are multiple writes, etc. in a row (not
> as much grabbing/releasing of the spinlock), and is the preferred way to do
> things in linux.
mv64360_read() need not be locked. The data is intrinsicly stale by the time 
the read has completed. The action on the Marvell to write the register is 
atomic, so you will not get partial reads, thus the data is only accurate at 
the instant it is read. By the time code sees it, the data, is not accurate.

Mark is right, locking must be abstracted. The basic r/w functions should do 
locking whatsoever, it is a performance hit on SMP and has no benefit. 
mv64360_modify() is right out. It should never have been included (no insult 
intended Mark), because it appears to have the same behavior (ie atomicity) 
as the mv64360_{read,write}() but it does not. I say the the IO be locked and 
bit twiddled explicity by the user. 

Just my 2 cents. 

Thanks
Brian 
 

>
> A few times now, I almost started to do that...looked at it and went off
> to do something else.  :)  Yes, I'm lazy.  Yes, I should do it.
> Eventually, I will (however, if you want to, I won't complain ;).
>
> Mark
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-09-12 13:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-09 17:31 Marvell MV64360 interrupt question Walter L. Wimer III
2005-09-09 19:09 ` Walter L. Wimer III
2005-09-12 12:56   ` Brian Waite
2005-09-09 19:27 ` Dale Farnsworth
2005-09-09 19:52   ` Walter L. Wimer III
2005-09-09 20:20   ` Walter L. Wimer III
2005-09-09 20:49     ` Dale Farnsworth
2005-09-09 21:18       ` Mark A. Greer
2005-09-12 13:05         ` Brian Waite

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).