On Fri, Feb 20, 2009 at 07:10:24AM -0700, Matthew Wilcox wrote:
> On Fri, Feb 20, 2009 at 07:09:51PM +0530, arun c wrote:
> > PCI host machine (PPC cpu) writes commands to
> > the PCI memory space of the (Coldfire CPU)
> > target device. Target device takes the command
> > and executes it.
> >
> > Target devices SDRAM is exposed over PCI to host.
> > A circular buffer residing on target memory is used
> > for command exchange.
> >
> > I should not allow host and target to play on the
> > buffer simultaneously in order to avoid corruption.
> >
> > Does anybody know how to implement a lock
> > suitable for this issue?
> >
> > or any lock less algorithm exists for communication
> > over PCI?
>
> I would have thought that a standard head and tail lockless queue would
> be perfect for your application. Expressed in C:
>
> struct queue {
> unsigned head;
> unsigned entries[QUEUE_SIZE];
> unsigned tail;
> }
>
> int queue_size(struct queue __iomem *q)
> {
> int size = readl(&q->head) - readl(&q->tail);
First, it would be alot more efficient if "head" and "tail" were
indexes into a base of the command list.
Then "queue_index = readl(&q)" would eliminate one MMIO read
(2000-3000 CPU cycles).
However, one of those two should be read-only and the other should
be write-only for the host. Target is a consumer for when the host
pushes a new command and host is consumer when the target completes
a command. Completions do not have to be in the same cacheline or
even same queue if there is some other way to associate completions
with an issued command (Hint: "tags").
Plenty of drivers are doing the same thing today but DMA-ing the
completion status into host memory and reading the command queue
from host memory. See how Gige networking drivers handle TX and RX
descriptors for examples.
hth,
grant
> if (size < 0)
> size += QUEUE_SIZE;
> return size;
> }
>
> int queue_empty(struct queue __iomem *q)
> {
> return readl(&q->head) == readl(&q->tail);
> }
>
> int queue_push(struct queue __iomem *q, unsigned item)
> {
> unsigned head = readl(&q->head) + 1;
> if (head == readl(&q->tail))
> return FAIL;
> writel(&q->entries[head], item);
> writel(&q->head, head);
> }
>
> Something like that anyway ... I obviously haven't tested or even
> compiled it.
>
> --
> Matthew Wilcox Intel Open Source Technology
> Centre
> "Bill, look, we understand that you're interested in selling us this
> operating system, but compare it to ours. We can't possibly take such
> a retrograde step."
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [email protected]
Please read the FAQ at http://kernelnewbies.org/FAQ