From: vinod.koul@intel.com (Vinod Koul)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 1/2] dma: at_xdmac: creation of the atmel eXtended DMA Controller driver
Date: Mon, 28 Jul 2014 22:17:50 +0530 [thread overview]
Message-ID: <20140728164750.GH8181@intel.com> (raw)
In-Reply-To: <20140728155431.GV2349@ldesroches-Latitude-E6320>
On Mon, Jul 28, 2014 at 05:54:31PM +0200, Ludovic Desroches wrote:
> > > +{
> > > + struct at_xdmac_desc *desc = txd_to_at_desc(tx);
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(tx->chan);
> > > + dma_cookie_t cookie;
> > > + unsigned long flags;
> > > +
> > > + spin_lock_irqsave(&atchan->lock, flags);
> > > + cookie = dma_cookie_assign(tx);
> > > +
> > > + dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n",
> > > + __func__, atchan, desc);
> > > + list_add_tail(&desc->xfer_node, &atchan->xfers_list);
> > > + if (list_is_singular(&atchan->xfers_list))
> > > + at_xdmac_start_xfer(atchan, desc);
> > so you dont start if list has more than 1 descriptors, why?
> Because I will let at_xdmac_advance_work managing the queue if not
> empty. So the only moment when I have to start the transfer in tx_submit
> is when I have only one transfer in the queue.
So xfers_list is current active descriptors right and if it is always going
to be singular why bother with a list?
> > > +static struct dma_async_tx_descriptor *
> > > +at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
> > > + size_t len, unsigned long flags)
> > > +{
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
> > > + struct at_xdmac_desc *first = NULL, *prev = NULL;
> > > + size_t remaining_size = len, xfer_size = 0, ublen;
> > > + dma_addr_t src_addr = src, dst_addr = dest;
> > > + u32 dwidth;
> > > + /*
> > > + * WARNING: The channel configuration is set here since there is no
> > > + * dmaengine_slave_config call in this case. Moreover we don't know the
> > > + * direction, it involves we can't dynamically set the source and dest
> > > + * interface so we have to use the same one. Only interface 0 allows EBI
> > > + * access. Hopefully we can access DDR through both ports (at least on
> > > + * SAMA5D4x), so we can use the same interface for source and dest,
> > > + * that solves the fact we don't know the direction.
> > and why do you need slave config for memcpy?
> Maybe the comments is not clear. With slave config we have the direction
> per to mem or mem to per. Of course when doing memcpy we don't need this
> information. But I use this information not only to set the transfer
> direction but also to set the interfaces to use for the source and dest
> (these interfaces depend on the connection on the matrix).
> So slave config was useful due to direction field to tell which interface
> to use as source and which one as dest.
> I am lucky because NAND and DDR are on the same interfaces so it's not a
> problem.
>
> This comment is more a warning for myself to keep in mind this possible
> issue in order to not have a device with NAND and DDR on different
> interfaces because it will be difficult to tell which interface is the
> source and which one is the dest.
Well in that case shouldnt NAND be treated like periphral and not memory?
> > > +static enum dma_status
> > > +at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
> > > + struct dma_tx_state *txstate)
> > > +{
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
> > > + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
> > > + struct at_xdmac_desc *desc, *_desc;
> > > + unsigned long flags;
> > > + enum dma_status ret;
> > > + int residue;
> > > + u32 cur_nda;
> > > +
> > > + ret = dma_cookie_status(chan, cookie, txstate);
> > > + if (ret == DMA_COMPLETE)
> > > + return ret;
> > > +
> > > + spin_lock_irqsave(&atchan->lock, flags);
> > > +
> > > + desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
> > > +
> > > + if (!desc->active_xfer)
> > > + dev_err(chan2dev(chan),
> > > + "something goes wrong, there is no active transfer\n");
> > We can query resiude even when tx_submit hasnt been invoked. You need to
> > return the full length in that case.
>
> Ok, I was not aware about this case.
>
> > > +
> > > + residue = desc->xfer_size;
> >
> > Also do check if txsate is NULL, in case just bail out here.
>
> Return value will be the one returned by dma_cookie_status?
Yes
> > > + */
> > > + list_del(&desc->xfer_node);
> > > + list_splice_init(&desc->descs_list, &atchan->free_descs_list);
> > shouldnt you move all the desc in active list in one shot ?
> >
>
> Sorry I don't get it. What are you suggesting by one shot?
Rather than invoking this per descriptor moving descriptors to
free_desc_list one by one, we can move all descriptors togther.
>
> > > +static void at_xdmac_tasklet(unsigned long data)
> > > +{
> > > + struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data;
> > > + struct at_xdmac_desc *desc;
> > > + u32 error_mask;
> > > +
> > > + dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
> > > + __func__, atchan->status);
> > > +
> > > + error_mask = AT_XDMAC_CIS_RBEIS
> > > + | AT_XDMAC_CIS_WBEIS
> > > + | AT_XDMAC_CIS_ROIS;
> > > +
> > > + if (at_xdmac_chan_is_cyclic(atchan)) {
> > > + at_xdmac_handle_cyclic(atchan);
> > > + } else if ((atchan->status & AT_XDMAC_CIS_LIS)
> > > + || (atchan->status & error_mask)) {
> > > + struct dma_async_tx_descriptor *txd;
> > > +
> > > + if (atchan->status & AT_XDMAC_CIS_RBEIS)
> > > + dev_err(chan2dev(&atchan->chan), "read bus error!!!");
> > > + else if (atchan->status & AT_XDMAC_CIS_WBEIS)
> > > + dev_err(chan2dev(&atchan->chan), "write bus error!!!");
> > > + else if (atchan->status & AT_XDMAC_CIS_ROIS)
> > > + dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
> > > +
> > > + desc = list_first_entry(&atchan->xfers_list,
> > > + struct at_xdmac_desc,
> > > + xfer_node);
> > > + dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc);
> > > + BUG_ON(!desc->active_xfer);
> > > +
> > > + txd = &desc->tx_dma_desc;
> > > +
> > > + at_xdmac_terminate_xfer(atchan, desc);
> > why terminate here? This looks wrong
>
> Why? What do you have in mind? It is not obvious for me that it is the
> wrong place.
The descriptor has completed. The terminate has special meaning. The user
can cancel all transactions by invoking terminate_all(). That implies to
clean up the channel and abort the transfers. The transfer is done so what
does it mean to terminate.
> > > + if (!atxdmac) {
> > > + dev_err(&pdev->dev, "can't allocate at_xdmac structure\n");
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + atxdmac->regs = base;
> > > + atxdmac->irq = irq;
> > > +
> > > + ret = devm_request_irq(&pdev->dev, atxdmac->irq, at_xdmac_interrupt, 0,
> > > + "at_xdmac", atxdmac);
> > and this can invoke your irq handler and you may not be ready. Second this
> > cause races with tasklet, so usualy recommednation is to use regular
> > request_irq()
>
> You mean it is specific to devm variant, isn't it?
Yes.
> > > + dma_cap_set(DMA_CYCLIC, atxdmac->dma.cap_mask);
> > > + dma_cap_set(DMA_MEMCPY, atxdmac->dma.cap_mask);
> > > + dma_cap_set(DMA_SLAVE, atxdmac->dma.cap_mask);
> > > + atxdmac->dma.dev = &pdev->dev;
> > > + atxdmac->dma.device_alloc_chan_resources = at_xdmac_alloc_chan_resources;
> > > + atxdmac->dma.device_free_chan_resources = at_xdmac_free_chan_resources;
> > > + atxdmac->dma.device_tx_status = at_xdmac_tx_status;
> > > + atxdmac->dma.device_issue_pending = at_xdmac_issue_pending;
> > > + atxdmac->dma.device_prep_dma_cyclic = at_xdmac_prep_dma_cyclic;
> > > + atxdmac->dma.device_prep_dma_memcpy = at_xdmac_prep_dma_memcpy;
> > > + atxdmac->dma.device_prep_slave_sg = at_xdmac_prep_slave_sg;
> > > + atxdmac->dma.device_control = at_xdmac_control;
> > > + atxdmac->dma.chancnt = nr_channels;
> > no caps, pls do implement that as you have cyclic dma too
>
> Sorry I don't understand what you mean here.
pls implement .device_slave_caps
> > > +static int at_xdmac_remove(struct platform_device *pdev)
> > > +{
> > > + struct at_xdmac *atxdmac = (struct at_xdmac*)platform_get_drvdata(pdev);
> > > + int i;
> > > +
> > > + at_xdmac_off(atxdmac);
> > > + of_dma_controller_free(pdev->dev.of_node);
> > > + dma_async_device_unregister(&atxdmac->dma);
> > > + clk_disable_unprepare(atxdmac->clk);
> > > +
> > > + synchronize_irq(atxdmac->irq);
> > > +
> > > + for (i = 0; i < atxdmac->dma.chancnt; i++) {
> > > + struct at_xdmac_chan *atchan = &atxdmac->chan[i];
> > > +
> > > + tasklet_kill(&atchan->tasklet);
> > > + at_xdmac_free_chan_resources(&atchan->chan);
> > > + }
> > and you can still get irq!
>
> Why? I thought deactivating irq on device side and calling synchronize
> irq will do the stuff.
what if we have buggy hardware or spurious interrupt!
>
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static const struct dev_pm_ops atmel_xdmac_dev_pm_ops = {
> > > + .prepare = atmel_xdmac_prepare,
> > > + .suspend_noirq = atmel_xdmac_suspend_noirq,
> > > + .resume_noirq = atmel_xdmac_resume_noirq,
> > > +};
> > no ifdef CONFIG_PM?
>
> I'll add it.
>
> > You might want to make them late_suspend and early_resume to allow
> > clients suspending first
>
> Ok, as I told before I was wondering which variant to use. For my
> knowledge, it will be the case also with noirq, isn't it? It is called
> after suspend_late.
Yes, thats why it makes sense for dmaengine drivers to use only late_suspend
and ealy_resume
--
~Vinod
WARNING: multiple messages have this Message-ID (diff)
From: Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
To: dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org,
plagnioj-sclMFOaUSTBWk0Htik3J/w@public.gmane.org,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
josh.wu-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org,
sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org
Subject: Re: [PATCH v3 1/2] dma: at_xdmac: creation of the atmel eXtended DMA Controller driver
Date: Mon, 28 Jul 2014 22:17:50 +0530 [thread overview]
Message-ID: <20140728164750.GH8181@intel.com> (raw)
In-Reply-To: <20140728155431.GV2349@ldesroches-Latitude-E6320>
On Mon, Jul 28, 2014 at 05:54:31PM +0200, Ludovic Desroches wrote:
> > > +{
> > > + struct at_xdmac_desc *desc = txd_to_at_desc(tx);
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(tx->chan);
> > > + dma_cookie_t cookie;
> > > + unsigned long flags;
> > > +
> > > + spin_lock_irqsave(&atchan->lock, flags);
> > > + cookie = dma_cookie_assign(tx);
> > > +
> > > + dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n",
> > > + __func__, atchan, desc);
> > > + list_add_tail(&desc->xfer_node, &atchan->xfers_list);
> > > + if (list_is_singular(&atchan->xfers_list))
> > > + at_xdmac_start_xfer(atchan, desc);
> > so you dont start if list has more than 1 descriptors, why?
> Because I will let at_xdmac_advance_work managing the queue if not
> empty. So the only moment when I have to start the transfer in tx_submit
> is when I have only one transfer in the queue.
So xfers_list is current active descriptors right and if it is always going
to be singular why bother with a list?
> > > +static struct dma_async_tx_descriptor *
> > > +at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
> > > + size_t len, unsigned long flags)
> > > +{
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
> > > + struct at_xdmac_desc *first = NULL, *prev = NULL;
> > > + size_t remaining_size = len, xfer_size = 0, ublen;
> > > + dma_addr_t src_addr = src, dst_addr = dest;
> > > + u32 dwidth;
> > > + /*
> > > + * WARNING: The channel configuration is set here since there is no
> > > + * dmaengine_slave_config call in this case. Moreover we don't know the
> > > + * direction, it involves we can't dynamically set the source and dest
> > > + * interface so we have to use the same one. Only interface 0 allows EBI
> > > + * access. Hopefully we can access DDR through both ports (at least on
> > > + * SAMA5D4x), so we can use the same interface for source and dest,
> > > + * that solves the fact we don't know the direction.
> > and why do you need slave config for memcpy?
> Maybe the comments is not clear. With slave config we have the direction
> per to mem or mem to per. Of course when doing memcpy we don't need this
> information. But I use this information not only to set the transfer
> direction but also to set the interfaces to use for the source and dest
> (these interfaces depend on the connection on the matrix).
> So slave config was useful due to direction field to tell which interface
> to use as source and which one as dest.
> I am lucky because NAND and DDR are on the same interfaces so it's not a
> problem.
>
> This comment is more a warning for myself to keep in mind this possible
> issue in order to not have a device with NAND and DDR on different
> interfaces because it will be difficult to tell which interface is the
> source and which one is the dest.
Well in that case shouldnt NAND be treated like periphral and not memory?
> > > +static enum dma_status
> > > +at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
> > > + struct dma_tx_state *txstate)
> > > +{
> > > + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
> > > + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
> > > + struct at_xdmac_desc *desc, *_desc;
> > > + unsigned long flags;
> > > + enum dma_status ret;
> > > + int residue;
> > > + u32 cur_nda;
> > > +
> > > + ret = dma_cookie_status(chan, cookie, txstate);
> > > + if (ret == DMA_COMPLETE)
> > > + return ret;
> > > +
> > > + spin_lock_irqsave(&atchan->lock, flags);
> > > +
> > > + desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
> > > +
> > > + if (!desc->active_xfer)
> > > + dev_err(chan2dev(chan),
> > > + "something goes wrong, there is no active transfer\n");
> > We can query resiude even when tx_submit hasnt been invoked. You need to
> > return the full length in that case.
>
> Ok, I was not aware about this case.
>
> > > +
> > > + residue = desc->xfer_size;
> >
> > Also do check if txsate is NULL, in case just bail out here.
>
> Return value will be the one returned by dma_cookie_status?
Yes
> > > + */
> > > + list_del(&desc->xfer_node);
> > > + list_splice_init(&desc->descs_list, &atchan->free_descs_list);
> > shouldnt you move all the desc in active list in one shot ?
> >
>
> Sorry I don't get it. What are you suggesting by one shot?
Rather than invoking this per descriptor moving descriptors to
free_desc_list one by one, we can move all descriptors togther.
>
> > > +static void at_xdmac_tasklet(unsigned long data)
> > > +{
> > > + struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data;
> > > + struct at_xdmac_desc *desc;
> > > + u32 error_mask;
> > > +
> > > + dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
> > > + __func__, atchan->status);
> > > +
> > > + error_mask = AT_XDMAC_CIS_RBEIS
> > > + | AT_XDMAC_CIS_WBEIS
> > > + | AT_XDMAC_CIS_ROIS;
> > > +
> > > + if (at_xdmac_chan_is_cyclic(atchan)) {
> > > + at_xdmac_handle_cyclic(atchan);
> > > + } else if ((atchan->status & AT_XDMAC_CIS_LIS)
> > > + || (atchan->status & error_mask)) {
> > > + struct dma_async_tx_descriptor *txd;
> > > +
> > > + if (atchan->status & AT_XDMAC_CIS_RBEIS)
> > > + dev_err(chan2dev(&atchan->chan), "read bus error!!!");
> > > + else if (atchan->status & AT_XDMAC_CIS_WBEIS)
> > > + dev_err(chan2dev(&atchan->chan), "write bus error!!!");
> > > + else if (atchan->status & AT_XDMAC_CIS_ROIS)
> > > + dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
> > > +
> > > + desc = list_first_entry(&atchan->xfers_list,
> > > + struct at_xdmac_desc,
> > > + xfer_node);
> > > + dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc);
> > > + BUG_ON(!desc->active_xfer);
> > > +
> > > + txd = &desc->tx_dma_desc;
> > > +
> > > + at_xdmac_terminate_xfer(atchan, desc);
> > why terminate here? This looks wrong
>
> Why? What do you have in mind? It is not obvious for me that it is the
> wrong place.
The descriptor has completed. The terminate has special meaning. The user
can cancel all transactions by invoking terminate_all(). That implies to
clean up the channel and abort the transfers. The transfer is done so what
does it mean to terminate.
> > > + if (!atxdmac) {
> > > + dev_err(&pdev->dev, "can't allocate at_xdmac structure\n");
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + atxdmac->regs = base;
> > > + atxdmac->irq = irq;
> > > +
> > > + ret = devm_request_irq(&pdev->dev, atxdmac->irq, at_xdmac_interrupt, 0,
> > > + "at_xdmac", atxdmac);
> > and this can invoke your irq handler and you may not be ready. Second this
> > cause races with tasklet, so usualy recommednation is to use regular
> > request_irq()
>
> You mean it is specific to devm variant, isn't it?
Yes.
> > > + dma_cap_set(DMA_CYCLIC, atxdmac->dma.cap_mask);
> > > + dma_cap_set(DMA_MEMCPY, atxdmac->dma.cap_mask);
> > > + dma_cap_set(DMA_SLAVE, atxdmac->dma.cap_mask);
> > > + atxdmac->dma.dev = &pdev->dev;
> > > + atxdmac->dma.device_alloc_chan_resources = at_xdmac_alloc_chan_resources;
> > > + atxdmac->dma.device_free_chan_resources = at_xdmac_free_chan_resources;
> > > + atxdmac->dma.device_tx_status = at_xdmac_tx_status;
> > > + atxdmac->dma.device_issue_pending = at_xdmac_issue_pending;
> > > + atxdmac->dma.device_prep_dma_cyclic = at_xdmac_prep_dma_cyclic;
> > > + atxdmac->dma.device_prep_dma_memcpy = at_xdmac_prep_dma_memcpy;
> > > + atxdmac->dma.device_prep_slave_sg = at_xdmac_prep_slave_sg;
> > > + atxdmac->dma.device_control = at_xdmac_control;
> > > + atxdmac->dma.chancnt = nr_channels;
> > no caps, pls do implement that as you have cyclic dma too
>
> Sorry I don't understand what you mean here.
pls implement .device_slave_caps
> > > +static int at_xdmac_remove(struct platform_device *pdev)
> > > +{
> > > + struct at_xdmac *atxdmac = (struct at_xdmac*)platform_get_drvdata(pdev);
> > > + int i;
> > > +
> > > + at_xdmac_off(atxdmac);
> > > + of_dma_controller_free(pdev->dev.of_node);
> > > + dma_async_device_unregister(&atxdmac->dma);
> > > + clk_disable_unprepare(atxdmac->clk);
> > > +
> > > + synchronize_irq(atxdmac->irq);
> > > +
> > > + for (i = 0; i < atxdmac->dma.chancnt; i++) {
> > > + struct at_xdmac_chan *atchan = &atxdmac->chan[i];
> > > +
> > > + tasklet_kill(&atchan->tasklet);
> > > + at_xdmac_free_chan_resources(&atchan->chan);
> > > + }
> > and you can still get irq!
>
> Why? I thought deactivating irq on device side and calling synchronize
> irq will do the stuff.
what if we have buggy hardware or spurious interrupt!
>
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static const struct dev_pm_ops atmel_xdmac_dev_pm_ops = {
> > > + .prepare = atmel_xdmac_prepare,
> > > + .suspend_noirq = atmel_xdmac_suspend_noirq,
> > > + .resume_noirq = atmel_xdmac_resume_noirq,
> > > +};
> > no ifdef CONFIG_PM?
>
> I'll add it.
>
> > You might want to make them late_suspend and early_resume to allow
> > clients suspending first
>
> Ok, as I told before I was wondering which variant to use. For my
> knowledge, it will be the case also with noirq, isn't it? It is called
> after suspend_late.
Yes, thats why it makes sense for dmaengine drivers to use only late_suspend
and ealy_resume
--
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2014-07-28 16:47 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-08 13:11 [PATCH v3 0/2] new Atmel DMA controller Ludovic Desroches
2014-07-08 13:11 ` Ludovic Desroches
2014-07-08 13:11 ` [PATCH v3 1/2] dma: at_xdmac: creation of the atmel eXtended DMA Controller driver Ludovic Desroches
2014-07-08 13:11 ` Ludovic Desroches
2014-07-25 7:16 ` Vinod Koul
2014-07-25 7:16 ` Vinod Koul
2014-07-28 15:54 ` Ludovic Desroches
2014-07-28 15:54 ` Ludovic Desroches
2014-07-28 16:47 ` Vinod Koul [this message]
2014-07-28 16:47 ` Vinod Koul
2014-09-10 13:23 ` Ludovic Desroches
2014-09-10 13:23 ` Ludovic Desroches
2014-09-11 5:14 ` Vinod Koul
2014-09-11 5:14 ` Vinod Koul
2014-09-11 6:29 ` Ludovic Desroches
2014-09-11 6:29 ` Ludovic Desroches
2014-07-08 13:11 ` [PATCH v3 2/2] ARM: dts: at_xdmac: add bindings documentation Ludovic Desroches
2014-07-08 13:11 ` Ludovic Desroches
2014-07-25 7:20 ` Vinod Koul
2014-07-25 7:20 ` Vinod Koul
2014-08-06 12:23 ` Ludovic Desroches
2014-08-06 12:23 ` Ludovic Desroches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140728164750.GH8181@intel.com \
--to=vinod.koul@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.