Re: [PATCH] dmaengine: async_xor, fix zero address issue when xor highmem page
2012/1/10 Shi Xuelin-B29237 b29...@freescale.com: Hello Dan Williams, Do you have any comment about this patch? Hi, sorrry for the delay. Thanks, Forrest -Original Message- From: Shi Xuelin-B29237 Sent: 2011年12月27日 14:31 To: vinod.k...@intel.com; dan.j.willi...@intel.com; linuxppc-dev@lists.ozlabs.org; linux-ker...@vger.kernel.org; Li Yang-R58472 Cc: Shi Xuelin-B29237 Subject: [PATCH] dmaengine: async_xor, fix zero address issue when xor highmem page From: Forrest shi b29...@freescale.com we may do_sync_xor high mem pages, in this case, page_address will return zero address which cause a failure. In what scenarios do we xor highmem? In the case of raid we currently always xor on kmalloc'd memory. this patch uses kmap_atomic before xor the pages and kunmap_atomic after it. Signed-off-by: b29...@freescale.com xuelin@freescale.com --- crypto/async_tx/async_xor.c | 16 1 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c index bc28337..5b416d1 100644 --- a/crypto/async_tx/async_xor.c +++ b/crypto/async_tx/async_xor.c @@ -26,6 +26,7 @@ #include linux/kernel.h #include linux/interrupt.h #include linux/mm.h +#include linux/highmem.h #include linux/dma-mapping.h #include linux/raid/xor.h #include linux/async_tx.h @@ -126,7 +127,7 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset, int src_cnt, size_t len, struct async_submit_ctl *submit) { int i; - int xor_src_cnt = 0; + int xor_src_cnt = 0, kmap_cnt=0; int src_off = 0; void *dest_buf; void **srcs; @@ -138,11 +139,13 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset, /* convert to buffer pointers */ for (i = 0; i src_cnt; i++) - if (src_list[i]) - srcs[xor_src_cnt++] = page_address(src_list[i]) + offset; + if (src_list[i]) { + srcs[xor_src_cnt++] = kmap_atomic(src_list[i], KM_USER1) + offset; + } + kmap_cnt = xor_src_cnt; I guess this works now that we have stack based kmap_atomic, but on older kernels you could not simultaneously map that many buffers with a single kmap slot. So if you resend, drop the second parameter to kmap_atomic. ...but unless you have a non md/raid456 use case in mind, or have patches to convert md/raid to xor straight out of the incoming biovecs I don't think this patch is needed right? ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFCv2 00/14]
On Wed, Jan 25, 2012 at 3:53 PM, Mark Salter msal...@redhat.com wrote: On Mon, 2012-01-23 at 14:07 -0700, Grant Likely wrote: Hey everyone, Here's the second RFC for the irq_domain patches. I could use some help testing now. I still expect there will be a few bugs. The series is based on v3.3-rc1, and I've pushed it out to my git server: Hi Grant, I converted arch/c6x over to the generic irq_domain support and have not had any problems in testing. The c6x virtual irq support was a nearly identical copy of the powerpc code, so the patch I ended up with mostly copied what you did in arch/powerpc. The c6x patch is on the tip of: g...@linux-c6x.org:/git/projects/linux-c6x-upstreaming irq-testing I think this probably belongs in your series, but I can push it separately if not. Yes, it should be in my series. Please post the patches and cc me so there is record of them in the mailing list archives and I'll pick them up. g. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: tlb flushing on Power
CC'ing linuxppc-dev... On 01/26/2012 08:18 AM, Seth Jennings wrote: Hey Dave, So I submitted the zsmalloc patches to lkml at the beginning of the year https://lkml.org/lkml/2012/1/9/389 I found there are two functions Nitin used in the mapping functions that are not supported in the powerpc arch: set_pte() and __flush_tlb_one(). set_pte() seems straightforward for the ppc64 case, although I think Power does some sort of pte hashing that might convolute it a little. My real question is how to achieve the function of __flush_tlb_one() on Power. I looked in Docuemntation/cachetlb.txt and it seems like the portable tlb flush functions are: void flush_tlb_all(void) void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) Of those options, flush_tlb_page() seems the closest to what __flush_tlb_one() does. However, we don't have a vma argument in our context (akaik) to send to it. I was wondering if you have any ideas. Any help is greatly appreciated! -- Seth -- Brian King Linux on Power Virtualization IBM Linux Technology Center ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC 1/2] irq_domain: Create common xlate functions that device drivers can use
On 01/25/2012 11:59 AM, Grant Likely wrote: On Tue, Jan 24, 2012 at 10:35 PM, Grant Likely grant.lik...@secretlab.ca wrote: On Tue, Jan 24, 2012 at 6:50 PM, Rob Herring robherri...@gmail.com wrote: On 01/24/2012 06:18 PM, Grant Likely wrote: Rather than having each interrupt controller driver creating its own barely unique .xlate function for irq_domain, create a library of translators which any driver can use directly. diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index e7379a3..5e497a0 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -110,6 +110,9 @@ struct irq_domain { void *host_data; irq_hw_number_t inval_irq; + /* Data for common irq xlate functions */ + unsigned int xlate_type; + How does this get set? Do we want interrupt controllers messing with the domain struct directly long term? It defaults to IRQ_TYPE_NONE in the alloc function and drivers can override it. Alternately it could be made part of the irq_domain_add() arguments, but I'm not thrilled with adding a whole bunch of arguments to the function prototype. Do you like this better (built on top of this patch)? Yes, I think it's better. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index ef2b1fe..7856c04 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -701,12 +701,10 @@ int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, unsigned long *out_hwirq, unsigned int *out_type) { - if (WARN(intsize 1, Bad intspec for %s: intsize=%i 1\n, - ctrlr-full_name, intsize)) + if (WARN_ON(intsize 1)) return -EINVAL; - *out_hwirq = intspec[0]; - *out_type = d-xlate_type; - return 0; + return irq_domain_xlate_onetwocell(d, ctrlr, intspec, 1, +out_hwirq, out_type); } EXPORT_SYMBOL_GPL(irq_domain_xlate_onecell); @@ -721,12 +719,10 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_type) { - if (WARN(intsize 2, Bad intspec for %s: intsize=%i 2\n, - ctrlr-full_name, intsize)) + if (WARN_ON(intsize 2)) return -EINVAL; - *out_hwirq = intspec[0]; - *out_type = intspec[1] IRQ_TYPE_SENSE_MASK; - return 0; + return irq_domain_xlate_onetwocell(d, ctrlr, intspec, intsize, +out_hwirq, out_type); } EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell); @@ -746,8 +742,7 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, const u32 *intspec, unsigned int intsize, unsigned long *out_hwirq, unsigned int *out_type) { - if (WARN(intsize 1, Bad intspec for %s: intsize=%i 1\n, - ctrlr-full_name, intsize)) + if (WARN_ON(intsize 1)) return -EINVAL; *out_hwirq = intspec[0]; *out_type = d-xlate_type; ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: FSL SPI driver question
Hi Bruce, On 01/25/12 20:49, bruce_leon...@selinc.com wrote: . . . Thanks for the reply. Yes I did find spidev_fdx.c and in fact copied it for my tests. I still see SPICLK active only during the time the 8308 is sending data (read cmd + address). Nothing happens with the clock after that when the NvRAM is ready to send data. Bruce ok, then I don't know. I doubt this is a spidev or FSP SPI driver problem though. Questions like: Could it be a HW problem ? Is the correct SPI mode used ? Does it work in u-boot ? Come to mind in a situation like this. Norbert. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: FSL SPI driver question
Norbert, ok, then I don't know. I doubt this is a spidev or FSP SPI driver problem though. Questions like: Could it be a HW problem ? Is the correct SPI mode used ? Does it work in u-boot ? Come to mind in a situation like this. Thanks for the suggestions. I finally found it in the wee hours this morning, and it was operator error. The CY14 by default powers up in the write protect state and from the factory is erased to all zeros. So my writes and subsequent reads appeared to fail by the fact that I could never read what I wrote. Guess I need better reading glasses in my old age :-/ Anyway, I'm happily up and talking using the Freescale SPI driver and spidev. Thanks for the help and sorry for the noise on the list. Bruce ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/1] fsldma: ignore end of segments interrupt
The mpc8349ea has been observed to generate spurious end of segments interrupts despite the fact that they are not enabled by this driver. Check for them and ignore them to avoid a kernel error message. Signed-off-by: Ira W. Snyder i...@ovro.caltech.edu Cc: Dan Williams dan.j.willi...@intel.com --- drivers/dma/fsldma.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 8a78154..7dc9689 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1052,6 +1052,16 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) stat = ~FSL_DMA_SR_EOLNI; } + /* +* This driver does not use this feature, therefore we shouldn't +* ever see this bit set in the status register. However, it has +* been observed on MPC8349EA parts. +*/ + if (stat FSL_DMA_SR_EOSI) { + chan_dbg(chan, irq: End-of-Segments INT\n); + stat = ~FSL_DMA_SR_EOSI; + } + /* check that the DMA controller is really idle */ if (!dma_is_idle(chan)) chan_err(chan, irq: controller not idle!\n); -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/1] carma-fpga: fix lockdep warning
Lockdep occasionally complains with the message: INFO: HARDIRQ-safe - HARDIRQ-unsafe lock order detected This is caused by calling videobuf_dma_unmap() under spin_lock_irq(). To fix the warning, we drop the lock before unmapping and freeing the buffer. Signed-off-by: Ira W. Snyder i...@ovro.caltech.edu Cc: Benjamin Herrenschmidt b...@kernel.crashing.org --- drivers/misc/carma/carma-fpga.c | 13 +++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 14e974b2..4fd896d 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c @@ -1079,6 +1079,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count, struct fpga_reader *reader = filp-private_data; struct fpga_device *priv = reader-priv; struct list_head *used = priv-used; + bool drop_buffer = false; struct data_buf *dbuf; size_t avail; void *data; @@ -1166,10 +1167,12 @@ have_buffer: * One of two things has happened, the device is disabled, or the * device has been reconfigured underneath us. In either case, we * should just throw away the buffer. +* +* Lockdep complains if this is done under the spinlock, so we +* handle it during the unlock path. */ if (!priv-enabled || dbuf-size != priv-bufsize) { - videobuf_dma_unmap(priv-dev, dbuf-vb); - data_free_buffer(dbuf); + drop_buffer = true; goto out_unlock; } @@ -1178,6 +1181,12 @@ have_buffer: out_unlock: spin_unlock_irq(priv-lock); + + if (drop_buffer) { + videobuf_dma_unmap(priv-dev, dbuf-vb); + data_free_buffer(dbuf); + } + return count; } -- 1.7.3.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/1] carma-fpga: fix race between data dumping and DMA callback
When the system is under heavy load, we occasionally saw a problem where the system would get a legitimate interrupt when they should be disabled. This was caused by the data_dma_cb() DMA callback unconditionally re-enabling FPGA interrupts even when data dumping is disabled. When data dumping was re-enabled, the irq handler would fire while a DMA was in progress. The BUG_ON(priv-inflight != NULL); during the second invocation of the DMA callback caused the system to crash. To fix the issue, the priv-enabled boolean is moved under the protection of the priv-lock spinlock. The DMA callback checks the boolean to know whether to re-enable FPGA interrupts before it returns. Now that it is fixed, the driver keeps FPGA interrupts disabled when it expects that they are disabled, fixing the bug. Signed-off-by: Ira W. Snyder i...@ovro.caltech.edu Cc: Benjamin Herrenschmidt b...@kernel.crashing.org --- drivers/misc/carma/carma-fpga.c | 101 +++--- 1 files changed, 61 insertions(+), 40 deletions(-) diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 4fd896d..0cfc5bf 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c @@ -560,6 +560,9 @@ static void data_enable_interrupts(struct fpga_device *priv) /* flush the writes */ fpga_read_reg(priv, 0, MMAP_REG_STATUS); + fpga_read_reg(priv, 1, MMAP_REG_STATUS); + fpga_read_reg(priv, 2, MMAP_REG_STATUS); + fpga_read_reg(priv, 3, MMAP_REG_STATUS); /* switch back to the external interrupt source */ iowrite32be(0x3F, priv-regs + SYS_IRQ_SOURCE_CTL); @@ -591,8 +594,12 @@ static void data_dma_cb(void *data) list_move_tail(priv-inflight-entry, priv-used); priv-inflight = NULL; - /* clear the FPGA status and re-enable interrupts */ - data_enable_interrupts(priv); + /* +* If data dumping is still enabled, then clear the FPGA +* status registers and re-enable FPGA interrupts +*/ + if (priv-enabled) + data_enable_interrupts(priv); spin_unlock_irqrestore(priv-lock, flags); @@ -708,6 +715,15 @@ static irqreturn_t data_irq(int irq, void *dev_id) spin_lock(priv-lock); + /* +* This is an error case that should never happen. +* +* If this driver has a bug and manages to re-enable interrupts while +* a DMA is in progress, then we will hit this statement and should +* start paying attention immediately. +*/ + BUG_ON(priv-inflight != NULL); + /* hide the interrupt by switching the IRQ driver to GPIO */ data_disable_interrupts(priv); @@ -762,11 +778,15 @@ out: */ static int data_device_enable(struct fpga_device *priv) { + bool enabled; u32 val; int ret; /* multiple enables are safe: they do nothing */ - if (priv-enabled) + spin_lock_irq(priv-lock); + enabled = priv-enabled; + spin_unlock_irq(priv-lock); + if (enabled) return 0; /* check that the FPGAs are programmed */ @@ -797,6 +817,9 @@ static int data_device_enable(struct fpga_device *priv) goto out_error; } + /* prevent the FPGAs from generating interrupts */ + data_disable_interrupts(priv); + /* hookup the irq handler */ ret = request_irq(priv-irq, data_irq, IRQF_SHARED, drv_name, priv); if (ret) { @@ -804,11 +827,13 @@ static int data_device_enable(struct fpga_device *priv) goto out_error; } - /* switch to the external FPGA IRQ line */ - data_enable_interrupts(priv); - - /* success, we're enabled */ + /* allow the DMA callback to re-enable FPGA interrupts */ + spin_lock_irq(priv-lock); priv-enabled = true; + spin_unlock_irq(priv-lock); + + /* allow the FPGAs to generate interrupts */ + data_enable_interrupts(priv); return 0; out_error: @@ -834,41 +859,40 @@ out_error: */ static int data_device_disable(struct fpga_device *priv) { - int ret; + spin_lock_irq(priv-lock); /* allow multiple disable */ - if (!priv-enabled) + if (!priv-enabled) { + spin_unlock_irq(priv-lock); return 0; + } + + /* +* Mark the device disabled +* +* This stops DMA callbacks from re-enabling interrupts +*/ + priv-enabled = false; - /* switch to the internal GPIO IRQ line */ + /* prevent the FPGAs from generating interrupts */ data_disable_interrupts(priv); + /* wait until all ongoing DMA has finished */ + while (priv-inflight != NULL) { + spin_unlock_irq(priv-lock); + wait_event(priv-wait, priv-inflight == NULL); + spin_lock_irq(priv-lock); + } + + spin_unlock_irq(priv-lock); + /*
Re: [PATCH 1/1] carma-fpga: fix race between data dumping and DMA callback
On Thu, 2012-01-26 at 13:00 -0800, Ira W. Snyder wrote: @@ -970,7 +984,13 @@ static ssize_t data_en_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fpga_device *priv = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, %u\n, priv-enabled); + int ret; + + spin_lock_irq(priv-lock); + ret = snprintf(buf, PAGE_SIZE, %u\n, priv-enabled); + spin_unlock_irq(priv-lock); + + return ret; } I don't think the lock buys you anything here. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFCv2 00/14]
On Wed, Jan 25, 2012 at 11:51 AM, Rob Herring robherri...@gmail.com wrote: On 01/25/2012 08:13 AM, Cousson, Benoit wrote: On 1/23/2012 10:53 PM, Rob Herring wrote: On 01/23/2012 03:07 PM, Grant Likely wrote: Hey everyone, Here's the second RFC for the irq_domain patches. I could use some help testing now. I still expect there will be a few bugs. The series is based on v3.3-rc1, and I've pushed it out to my git server: git://git.secretlab.ca/git/linux-2.6.git irqdomain/next Can you post to linux-arm-kernel too so people are aware of this work and stop posting dead-end irqdomain patches. Good point, I have two pending series that are using the irq_domain_add() so far, so it will be good to have that branch pulled in arm-soc. I tested what you had as of this morning and it works fine for me. Looks like the only diff is the VExpress code. I'm working on rebasing my domain support for generic irqchip now. In fact your generic irqchip should even avoid us to use irq_domain_add_legacy() since both GPIO and OMAP3 intc are already using the irqchip. I guess you are not going to change the interface so the patches I did on your previous branch to try them should be good already, isn't it? I've got it rebased on top of Grant's tree. I will send it out soon. One problem that still remains is it breaks x86 and any platform using generic irq chip, but not selecting IRQ_DOMAIN. Grant, do you plan to enable IRQ_DOMAIN for x86 in your series? MIPS may also need fixing. I've got the x86 fix in my tree now. It will be part of the next merge. MIPS, Microblaze and OpenRISC cannot turn on CONFIG_IRQ_DOMAIN without rework. I just hacked together the microblaze version, but Michal will have to verify that it is correct. I just posted it. It will be similar for the other two. The real problem is sparc which does something entirely different for irqs. Rather than resolving irqs on-demand, it calculates the Linux irq numbers at boot time for every node in the tree. The irq_domains will need to be set up for all interrupt controllers before sparc begins it's big walk of the tree to resolve interrupts. I haven't dug into everything that needs to be done to support this. I don't think you can count on turning on IRQ_DOMAIN on all architectures just yet. Adding irq_domain support directly to irq_generic_chip is going to be difficult for that reason. However, it would be useful to have an irq_domain+irq_generic_chip wrapper that can be enabled only when IRQ_DOMAIN is enabled. g. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC] dmaengine/dma_slave: add context parameter to prep_slave_sg callback
As we agreed during our discussion about adding DMA Engine support for RapidIO subsystem, RapidIO and similar clients may benefit from adding an extra context parameter to device_prep_slave_sg() callback. See https://lkml.org/lkml/2011/10/24/275 for more details. Adding the context parameter will allow to pass client/target specific information associated with an individual data transfer request. In the case of RapidIO support this additional information consists of target destination ID and its buffer address (which is not mapped into the local CPU memory space). Because a single RapidIO-capable DMA channel may queue data transfer requests to different target devices, the per-request configuration is required. The proposed change eliminates need for new subsystem-specific API. Existing DMA_SLAVE clients will ignore the new parameter. This RFC only demonstrates the API change and does not include corresponding changes to existing DMA_SLAVE clients. Complete set of patches will be provided after (if) this API change is accepted. Signed-off-by: Alexandre Bounine alexandre.boun...@idt.com Cc: Jassi Brar jaswinder.si...@linaro.org Cc: Russell King r...@arm.linux.org.uk Cc: Kumar Gala ga...@kernel.crashing.org Cc: Matt Porter mpor...@kernel.crashing.org Cc: Li Yang le...@freescale.com --- include/linux/dmaengine.h |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 679b349..79d71bb 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -575,7 +575,7 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, - unsigned long flags); + unsigned long flags, void *context); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction); @@ -607,12 +607,13 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, void *buf, size_t len, - enum dma_transfer_direction dir, unsigned long flags) + enum dma_transfer_direction dir, unsigned long flags, void *context) { struct scatterlist sg; sg_init_one(sg, buf, len); - return chan-device-device_prep_slave_sg(chan, sg, 1, dir, flags); + return chan-device-device_prep_slave_sg(chan, sg, 1, dir, flags, + context); } static inline int dmaengine_terminate_all(struct dma_chan *chan) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: tlb flushing on Power
On Thu, 2012-01-26 at 08:41 -0600, Brian King wrote: CC'ing linuxppc-dev... On 01/26/2012 08:18 AM, Seth Jennings wrote: Hey Dave, So I submitted the zsmalloc patches to lkml at the beginning of the year https://lkml.org/lkml/2012/1/9/389 I found there are two functions Nitin used in the mapping functions that are not supported in the powerpc arch: set_pte() and __flush_tlb_one(). .../... The arch management of page tables can be tricky indeed :-) I need to have a better understanding of what you are doing to see how I can try to adapt it to power. set_pte() is long gone on all archs really (or if it's still there it's not meant to be used as is), use set_pte_at(). __flush_tlb_one() doesn't mean anything as an arch independent functionality. We have a local_flush_tlb_page() that -might- do what you want but why in hell is that patch not using proper existing interfaces ? Can you explain to me a bit more the whole business in this patch set about doing kmap_atomic() vs. manually trying to populate the PTEs ? Why not just use two kmap atomic entries ? If interrupts are disabled kmap_atomic() should give you contiguous ones I suppose (unless NMIs are allowed to use kmap_atomic, are they ?) Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: tlb flushing on Power
On 01/26/2012 01:39 PM, Benjamin Herrenschmidt wrote: Can you explain to me a bit more the whole business in this patch set about doing kmap_atomic() vs. manually trying to populate the PTEs ? They're compressing pages and the allocator is trying getting very poor packing of compressed pages in to PAGE_SIZE chunks. So, they're moving to 2-page allocations that they need to be mapped contiguously to make it easier on the users of the allocator. Why not just use two kmap atomic entries ? If interrupts are disabled kmap_atomic() should give you contiguous ones I suppose I think you and I are at least on the same page on this one: https://lkml.org/lkml/2012/1/26/355 (unless NMIs are allowed to use kmap_atomic, are they ?) Surely they can't be. Even if they could use it, they'd have to return the __kmap_atomic_idx back to the place where it started before they returned, so the interrupted code wouldn't notice. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: tlb flushing on Power
On Thu, 2012-01-26 at 14:30 -0800, Dave Hansen wrote: On 01/26/2012 01:39 PM, Benjamin Herrenschmidt wrote: Can you explain to me a bit more the whole business in this patch set about doing kmap_atomic() vs. manually trying to populate the PTEs ? They're compressing pages and the allocator is trying getting very poor packing of compressed pages in to PAGE_SIZE chunks. So, they're moving to 2-page allocations that they need to be mapped contiguously to make it easier on the users of the allocator. Why not just use two kmap atomic entries ? If interrupts are disabled kmap_atomic() should give you contiguous ones I suppose I think you and I are at least on the same page on this one: https://lkml.org/lkml/2012/1/26/355 Right. We probably want to document this somewhere if we start relying on that behaviour or at the very least add a WARN_ON() and fail from the compressed allocator if we end up with non-contiguous pages. (unless NMIs are allowed to use kmap_atomic, are they ?) Surely they can't be. Even if they could use it, they'd have to return the __kmap_atomic_idx back to the place where it started before they returned, so the interrupted code wouldn't notice. Ah indeed, that's for talking before I had breakfast :-) Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[no subject]
Hi, I'm using the 3.0.3 kernel on an MPC8308 and have turned on GPIO support (CONFIG_GPIOLIB = Y) because the SPI sub-system needed to use it for the GPIO pin I'm using as a CS to a NvRAM part. I also have some jumpers on the processor GPIO pins and I thought it would be really slick to use the built in GPIO support in the kernel rather than roll my own driver to read five pins. So I've got GPIO sysfs support turned on (CONFIG_GPIO_SYSFS = Y) and everything shows up in /sys/class/gpio and works as advertised. Really nice. The problem is we've got a number of other things hooked up to the GPIO pins that it would be very bad if someone from user space played with them, like our FPGA configuration pin. Some one toggles that and our box goes stupid. So what I'm wondering is if there's a way, preferably via the device tree, to limit the GPIOs that GPIO Lib exposes to user space? I tried the following in my device tree without success: gpio1: gpio@c00 { #gpio-cells = 2; device_type = gpio; compatible = fsl,mpc8308-gpio, fsl,mpc8349-gpio; reg = 0xc00 0x18; interrupts = 74 0x8; interrupt-parent = ipic; gpio-controller; gpios = gpio1 0 0 gpio1 1 0 gpio1 2 0 gpio1 3 0 gpio1 4 0 gpio1 5 0 gpio1 6 0; }; I also thought maybe a separate child node of the gpio1 node, but I think it would require a compatible attribute which would mean a driver to bind it to, and the whole point is to avoid writing a driver if someone else has already got something that will work. Thanks. Bruce ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Question about GPIO Lib
(This time with a subject line, sorry) Hi, I'm using the 3.0.3 kernel on an MPC8308 and have turned on GPIO support (CONFIG_GPIOLIB = Y) because the SPI sub-system needed to use it for the GPIO pin I'm using as a CS to a NvRAM part. I also have some jumpers on the processor GPIO pins and I thought it would be really slick to use the built in GPIO support in the kernel rather than roll my own driver to read five pins. So I've got GPIO sysfs support turned on (CONFIG_GPIO_SYSFS = Y) and everything shows up in /sys/class/gpio and works as advertised. Really nice. The problem is we've got a number of other things hooked up to the GPIO pins that it would be very bad if someone from user space played with them, like our FPGA configuration pin. Some one toggles that and our box goes stupid. So what I'm wondering is if there's a way, preferably via the device tree, to limit the GPIOs that GPIO Lib exposes to user space? I tried the following in my device tree without success: gpio1: gpio@c00 { #gpio-cells = 2; device_type = gpio; compatible = fsl,mpc8308-gpio, fsl,mpc8349-gpio; reg = 0xc00 0x18; interrupts = 74 0x8; interrupt-parent = ipic; gpio-controller; gpios = gpio1 0 0 gpio1 1 0 gpio1 2 0 gpio1 3 0 gpio1 4 0 gpio1 5 0 gpio1 6 0; }; I also thought maybe a separate child node of the gpio1 node, but I think it would require a compatible attribute which would mean a driver to bind it to, and the whole point is to avoid writing a driver if someone else has already got something that will work. Thanks. Bruce ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Another FSL SPI driver question (warning long post)
Hi Kumar, I'm using the 3.0.3 kernel on an MPC8308 and utilizing the spi_fsl_spi driver to talk with an Cypress NvRAM device. I've gotten that working now, but I've come across something I don't understand in the driver and I'm not sure if it's just me or if there's a bug. My issue relates to chip selects, their active state, and their specification in the device tree (lots of moving parts here, so I hope I describe it well enough to be understood). The chip select for the NvRAM is active low, but setting everything up they way I _think_ it should be for an active low signal gets me an active high signal. The device tree entry is: spi@7000 { #address-cells = 1; #size-cells = 0; cell-index = 0; compatible = fsl,spi; reg = 0x7000 0x1000; interrupts = 16 0x8; interrupt-parent = ipic; mode = cpu; gpios = gpio1 16 1; nvram@0 { compatible = spidev; spi-max-frequency = 4000; reg = 0; }; }; And the relevant driver code is the fsl_spi_chipselect and the fsl_spi_cs_control functions shown below (line numbers are for reference only and don't match lines numbers in .../drivers/spi/spi_fsl_spi.c): 1 static void fsl_spi_chipselect(struct spi_device *spi, int value) 2 { 3 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi-master); 4 struct fsl_spi_platform_data *pdata = spi-dev.parent-platform_data; 5 bool pol = spi-mode SPI_CS_HIGH; 6 struct spi_mpc8xxx_cs *cs = spi-controller_state; 7 8 if (value == BITBANG_CS_INACTIVE) { 9 if (pdata-cs_control) 10 pdata-cs_control(spi, !pol); 11 } 12 13 if (value == BITBANG_CS_ACTIVE) { 14 mpc8xxx_spi-rx_shift = cs-rx_shift; 15 mpc8xxx_spi-tx_shift = cs-tx_shift; 16 mpc8xxx_spi-get_rx = cs-get_rx; 17 mpc8xxx_spi-get_tx = cs-get_tx; 18 19 fsl_spi_change_mode(spi); 20 21 if (pdata-cs_control) 22 pdata-cs_control(spi, pol); 23 } 24 } 25 26 static void fsl_spi_cs_control(struct spi_device *spi, bool on) 27 { 28 struct device *dev = spi-dev.parent; 29 struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev-platform_data); 30 u16 cs = spi-chip_select; 31 int gpio = pinfo-gpios[cs]; 32 bool alow = pinfo-alow_flags[cs]; 33 34 gpio_set_value(gpio, on ^ alow); 35 } The variable pol comes from spi-mode SPI_CS_HIGH (line 5) and spi-mode gets it's value based on the spi-cs-high attribute in the device tree via .../drivers/of/of_spi.c like this: if (of_find_property(nc, spi-cs-high, NULL)) spi-mode |= SPI_CS_HIGH; In my case I want an active low CS so I don't include this attribute and spi-mode doesn't get the bit set. alow (line 32) ultimately comes from the flags part of the gpios specifier in the SPI node of my device tree via the of_fsl_spi_probe function like this: gpio = of_get_gpio_flags(np, i, flags); - flags gets a direct copy of flags in the gpios specifier pinfo-alow_flags[i] = flags OF_GPIO_ACTIVE_LOW; OF_GPIO_ACTIVE_LOW is an enum with a value of 0x1, implying that a value of 1 in the flags in my gpios specifier is saying the GPIO signal is active low. So if my understanding is right, I've got everything set up in my device tree correctly to have an active low CS. Now to the crux of the problem, line 34, the gpio_set_value call. When an SPI transaction is started and the CS needs to be driven to it's active state (low in my case) fsl_spi_chipselect is called with value = BITBANG_CS_ACTIVE, which leads to line 22, calling fsl_spi_cs_control with pol = 0 because spi-mode doesn't have the SPI_CS_HIGH bit set (line 5) which becomes on in fsl_spi_cs_control. alow = 1(line 32) because flags is 1 in the gpios specifier. on = 0 XORed with alow = 1 equals 1 when gpio_set_value is called, setting my chipselect HIGH not low. Then when the transaction is done fsl_spi_chipselect is called with value = BITBANG_CS_INACTIVE which leads to line 10 calling fsl_spi_cs_control with !pol = 1, alow is still a 1 and 1 XOR 1 = 0 when gpio_set_value is called, setting my chipselect to LOW. I did an experiment in which I added the spi-cs-high attribute to my device tree (which should have made the signal active high) and the result was the signal operated in the opposite way from what the name of the attribute implies. So (if my understanding of the device tree entries is correct) the logic on line 34 appears to be flawed, but since I'm not 100% sure of my understanding I wanted to ask people smarter than I am. More over, I don't think I understand why a device tree entry is used to indicate which state to change the chipselect to. Wouldn't it make more sense if lines 10 and 22 pass in a 1 for set the CS to the active state and a 0 for set the CS to the inactive