* [net-next-2.6 PATCH v2] can: SJA1000: generic OF platform bus driver
From: Wolfgang Grandegger @ 2009-05-22 14:46 UTC (permalink / raw)
To: Linux Netdev List; +Cc: linuxppc-dev, devicetree-discuss
This patch adds a generic driver for SJA1000 chips on the OpenFirmware
platform bus found on embedded PowerPC systems. You need a SJA1000 node
definition in your flattened device tree source (DTS) file similar to:
can@3,100 {
compatible = "nxp,sja1000";
reg = <3 0x100 0x80>;
clock-frequency = <8000000>;
cdr-reg = <0x48>;
ocr-reg = <0x0a>;
interrupts = <2 0>;
interrupt-parent = <&mpic>;
};
See also Documentation/powerpc/dts-bindings/can/sja1000.txt.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
Documentation/powerpc/dts-bindings/can/sja1000.txt | 37 +++
drivers/net/can/Kconfig | 9
drivers/net/can/sja1000/Makefile | 1
drivers/net/can/sja1000/sja1000_of_platform.c | 215 +++++++++++++++++++++
4 files changed, 262 insertions(+)
Index: net-next-2.6/drivers/net/can/Kconfig
===================================================================
--- net-next-2.6.orig/drivers/net/can/Kconfig
+++ net-next-2.6/drivers/net/can/Kconfig
@@ -51,6 +51,15 @@ config CAN_SJA1000_PLATFORM
boards from Phytec (http://www.phytec.de) like the PCM027,
PCM038.
+config CAN_SJA1000_OF_PLATFORM
+ depends on CAN_SJA1000 && PPC_OF
+ tristate "Generic OF Platform Bus based SJA1000 driver"
+ ---help---
+ This driver adds support for the SJA1000 chips connected to
+ the OpenFirmware "platform bus" found on embedded systems with
+ OpenFirmware bindings, e.g. if you have a PowerPC based system
+ you may want to enable this option.
+
config CAN_EMS_PCI
tristate "EMS CPC-PCI and CPC-PCIe Card"
depends on PCI && CAN_SJA1000
Index: net-next-2.6/drivers/net/can/sja1000/Makefile
===================================================================
--- net-next-2.6.orig/drivers/net/can/sja1000/Makefile
+++ net-next-2.6/drivers/net/can/sja1000/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
+obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
Index: net-next-2.6/drivers/net/can/sja1000/sja1000_of_platform.c
===================================================================
--- /dev/null
+++ net-next-2.6/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -0,0 +1,215 @@
+/*
+ * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus
+ *
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This is a generic driver for SJA1000 chips on the OpenFirmware platform
+ * bus found on embedded PowerPC systems. You need a SJA1000 CAN node
+ * definition in your flattened device tree source (DTS) file similar to:
+ *
+ * can@3,100 {
+ * compatible = "philips,sja1000";
+ * reg = <3 0x100 0x80>;
+ * clock-frequency = <8000000>;
+ * cdr-reg = <0x48>;
+ * ocr-reg = <0x0a>;
+ * interrupts = <2 0>;
+ * interrupt-parent = <&mpic>;
+ * };
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME "sja1000_of_platform"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus");
+MODULE_LICENSE("GPL v2");
+
+#define SJA1000_OFP_CAN_CLOCK (16000000 / 2)
+
+#define SJA1000_OFP_OCR OCR_TX0_PULLDOWN
+#define SJA1000_OFP_CDR (CDR_CBP | CDR_CLK_OFF)
+
+static u8 sja1000_ofp_read_reg(const struct net_device *dev, int reg)
+{
+ return in_8((void __iomem *)(dev->base_addr + reg));
+}
+
+static void sja1000_ofp_write_reg(const struct net_device *dev, int reg, u8 val)
+{
+ out_8((void __iomem *)(dev->base_addr + reg), val);
+}
+
+static int __devexit sja1000_ofp_remove(struct of_device *ofdev)
+{
+ struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+ struct device_node *np = ofdev->node;
+ struct resource res;
+
+ dev_set_drvdata(&ofdev->dev, NULL);
+
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
+ iounmap((void __iomem *)dev->base_addr);
+ irq_dispose_mapping(dev->irq);
+
+ of_address_to_resource(np, 0, &res);
+ release_mem_region(res.start, resource_size(&res));
+
+ return 0;
+}
+
+static int __devinit sja1000_ofp_probe(struct of_device *ofdev,
+ const struct of_device_id *id)
+{
+ struct device_node *np = ofdev->node;
+ struct net_device *dev;
+ struct sja1000_priv *priv;
+ struct resource res;
+ const u32 *prop;
+ int err, irq, res_size, prop_size;
+ void __iomem *base;
+
+ err = of_address_to_resource(np, 0, &res);
+ if (err) {
+ dev_err(&ofdev->dev, "invalid address\n");
+ return err;
+ }
+
+ res_size = resource_size(&res);
+
+ if (!request_mem_region(res.start, res_size, DRV_NAME)) {
+ dev_err(&ofdev->dev, "couldn't request %#x..%#x\n",
+ res.start, res.end);
+ return -EBUSY;
+ }
+
+ base = ioremap_nocache(res.start, res_size);
+ if (!base) {
+ dev_err(&ofdev->dev, "couldn't ioremap %#x..%#x\n",
+ res.start, res.end);
+ err = -ENOMEM;
+ goto exit_release_mem;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq == NO_IRQ) {
+ dev_err(&ofdev->dev, "no irq found\n");
+ err = -ENODEV;
+ goto exit_unmap_mem;
+ }
+
+ dev = alloc_sja1000dev(0);
+ if (!dev) {
+ err = -ENOMEM;
+ goto exit_dispose_irq;
+ }
+
+ priv = netdev_priv(dev);
+
+ priv->read_reg = sja1000_ofp_read_reg;
+ priv->write_reg = sja1000_ofp_write_reg;
+
+ prop = of_get_property(np, "clock-frequency", &prop_size);
+ if (prop && (prop_size == sizeof(u32)))
+ priv->can.clock.freq = *prop;
+ else
+ priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK;
+
+ prop = of_get_property(np, "ocr-reg", &prop_size);
+ if (prop && (prop_size == sizeof(u32)))
+ priv->ocr = (u8)*prop;
+ else
+ priv->ocr = SJA1000_OFP_OCR;
+
+ prop = of_get_property(np, "cdr-reg", &prop_size);
+ if (prop && (prop_size == sizeof(u32)))
+ priv->cdr = (u8)*prop;
+ else
+ priv->cdr = SJA1000_OFP_CDR;
+
+ priv->irq_flags = IRQF_SHARED;
+
+ dev->irq = irq;
+ dev->base_addr = (unsigned long)base;
+
+ dev_info(&ofdev->dev,
+ "base=0x%lx irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n",
+ dev->base_addr, dev->irq, priv->can.clock.freq,
+ priv->ocr, priv->cdr);
+
+ dev_set_drvdata(&ofdev->dev, dev);
+ SET_NETDEV_DEV(dev, &ofdev->dev);
+
+ err = register_sja1000dev(dev);
+ if (err) {
+ dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
+ DRV_NAME, err);
+ goto exit_free_sja1000;
+ }
+
+ return 0;
+
+exit_free_sja1000:
+ free_sja1000dev(dev);
+exit_dispose_irq:
+ irq_dispose_mapping(irq);
+exit_unmap_mem:
+ iounmap(base);
+exit_release_mem:
+ release_mem_region(res.start, res_size);
+
+ return err;
+}
+
+static struct of_device_id __devinitdata sja1000_ofp_table[] = {
+ {.compatible = "philips,sja1000"},
+ {.compatible = "nxp,sja1000"},
+ {},
+};
+
+static struct of_platform_driver sja1000_ofp_driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .probe = sja1000_ofp_probe,
+ .remove = __devexit_p(sja1000_ofp_remove),
+ .match_table = sja1000_ofp_table,
+};
+
+static int __init sja1000_ofp_init(void)
+{
+ return of_register_platform_driver(&sja1000_ofp_driver);
+}
+module_init(sja1000_ofp_init);
+
+static void __exit sja1000_ofp_exit(void)
+{
+ return of_unregister_platform_driver(&sja1000_ofp_driver);
+};
+module_exit(sja1000_ofp_exit);
Index: net-next-2.6/Documentation/powerpc/dts-bindings/can/sja1000.txt
===================================================================
--- /dev/null
+++ net-next-2.6/Documentation/powerpc/dts-bindings/can/sja1000.txt
@@ -0,0 +1,37 @@
+Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
+
+Required properties:
+
+- compatible : should be "nxp,sja1000".
+- reg : should specify the chip select, address offset and size used
+ for the chip depending on the bus it is connected to.
+- interrupts: property with a value describing the interrupt source
+ (number and sensitivity) for that device. The encoding depends
+ on the type of interrupt controller used.
+
+Optional properties:
+
+- interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for that device.
+- clock-frequency : CAN system clock frequency in Hz, which is normally
+ half of the oscillator clock frequency. If not specified, a
+ default value of 8000000 (8 MHz) is used.
+- cdr-reg : value of the SJA1000 clock divider register according to
+ the SJA1000 data sheet. If not specified, a default value of
+ 0x48 is used.
+- ocr-reg : value of the SJA1000 output control register according to
+ the SJA1000 data sheet. If not specified, a default value of
+ 0x0a is used.
+
+Examples:
+
+can@3,100 {
+ compatible = "nxp,sja1000";
+ reg = <3 0x100 0x80>;
+ clock-frequency = <8000000>;
+ cdr-reg = <0x48>;
+ ocr-reg = <0x0a>;
+ interrupts = <2 0>;
+ interrupt-parent = <&mpic>;
+};
+
^ permalink raw reply
* Re: [PATCH] mpc52xx_psc_spi: Convert to cs_control callback
From: Jon Smirl @ 2009-05-22 13:29 UTC (permalink / raw)
To: Anton Vorontsov
Cc: linuxppc-dev, Andrew Morton, David Brownell, spi-devel-general
In-Reply-To: <20090430223114.GA12571@oksana.dev.rtsoft.ru>
On Thu, Apr 30, 2009 at 6:31 PM, Anton Vorontsov
<avorontsov@ru.mvista.com> wrote:
> mpc52xx_psc_spi driver is the last user of the legacy activate_cs
> and deactivate_cs callbacks, so convert the driver to the cs_control
This driver is missing a call to of_register_spi_devices(master, op->node);
Here's how I added it, but it could be done more cleanly.
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 68c77a9..fe0658a 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
+#include <linux/of_spi.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
@@ -370,24 +371,24 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq,
void *dev_id)
}
/* bus_num is used only for the case dev->platform_data == NULL */
-static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+static int __init mpc52xx_psc_spi_do_probe(struct of_device *op, u32 regaddr,
u32 size, unsigned int irq, s16 bus_num)
{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
+ struct fsl_spi_platform_data *pdata = op->dev.platform_data;
struct mpc52xx_psc_spi *mps;
struct spi_master *master;
int ret;
- master = spi_alloc_master(dev, sizeof *mps);
+ master = spi_alloc_master(&op->dev, sizeof *mps);
if (master == NULL)
return -ENOMEM;
- dev_set_drvdata(dev, master);
+ dev_set_drvdata(&op->dev, master);
mps = spi_master_get_devdata(master);
mps->irq = irq;
if (pdata == NULL) {
- dev_warn(dev, "probe called without platform data, no "
+ dev_warn(&op->dev, "probe called without platform data, no "
"(de)activate_cs function will be called\n");
mps->activate_cs = NULL;
mps->deactivate_cs = NULL;
@@ -407,7 +408,7 @@ static int __init mpc52xx_psc_spi_do_probe(struct
device *dev, u32 regaddr,
mps->psc = ioremap(regaddr, size);
if (!mps->psc) {
- dev_err(dev, "could not ioremap I/O port range\n");
+ dev_err(&op->dev, "could not ioremap I/O port range\n");
ret = -EFAULT;
goto free_master;
}
@@ -439,6 +440,8 @@ static int __init mpc52xx_psc_spi_do_probe(struct
device *dev, u32 regaddr,
if (ret < 0)
goto unreg_master;
+ of_register_spi_devices(master, op->node);
+
return ret;
unreg_master:
@@ -495,7 +498,7 @@ static int __init mpc52xx_psc_spi_of_probe(struct
of_device *op,
id = *psc_nump + 1;
}
- return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
+ return mpc52xx_psc_spi_do_probe(op, (u32)regaddr64, (u32)size64,
irq_of_parse_and_map(op->node, 0), id);
}
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply related
* Re: [PATCH] mmc: Add fsl,esdhc as a valid compatible to bind against
From: Pierre Ossman @ 2009-05-22 11:53 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1241790769-3843-1-git-send-email-galak@kernel.crashing.org>
[-- Attachment #1: Type: text/plain, Size: 504 bytes --]
On Fri, 8 May 2009 08:52:49 -0500
Kumar Gala <galak@kernel.crashing.org> wrote:
> We plan to use fsl,esdhc going forward as the base compatible so update
> the driver to bind against it.
>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
Applied.
Rgds
--
-- Pierre Ossman
WARNING: This correspondence is being monitored by the
Swedish government. Make sure your server uses encryption
for SMTP traffic and consider using PGP for end-to-end
encryption.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: Ian Campbell @ 2009-05-22 11:11 UTC (permalink / raw)
To: Becky Bruce
Cc: FUJITA Tomonori, linuxppc-dev@ozlabs.org, Jeremy Fitzhardinge,
linux-kernel@vger.kernel.org
In-Reply-To: <E6DAA792-9923-4B76-9759-6955AABE3EAB@kernel.crashing.org>
On Thu, 2009-05-21 at 14:27 -0400, Becky Bruce wrote:
> I can work with that, but it's going to be a bit inefficient, as I
> actually need the dma_addr_t, not the phys_addr_t, so I'll have to
> convert. In every case, this is a conversion I've already done and
> that I need in the calling code as well.
Does
dma_addr_t dma_map_range(struct device *hwdev, phys_addr_t addr,
size_t size);
work for you?
If the range does not need mapping then it returns the dma address, if
you needed to calculate the dma address anyway to figure out if mapping
is required then this is fine. If the range does need mapping then it
returns NULL.
This subsumes many of the phys->dma address conversions which would
otherwise be done in the callers. IMHO this is an architecture specific
detail which should be pushed down into the arch code as much as
possible. The only ones which I don't think can be pushed down are the
ones in swiotlb_virt_to_bus/swiotlb_bus_to_virt.
BTW do you need swiotlb_bus_to_virt to be __weak or is the fact that it
is implemented in terms of swiotlb_bus_to_phys sufficient?
I have an appointment all afternoon and it's a bank holiday on Monday
but here is my WIP patch as an example of what I'm thinking. Obviously
some cleanups are still very much required:
* The Xen specific stuff in arch/x86/include/asm/dma-mapping.h
clearly needs to be properly abstracted away (I just stuck it
there for testing).
* swiotlb_phys_to_bus and swiotlb_bus_to_phys need to move to
arch/*/include/asm/dma-mapping.h instead of being __weak
* Maybe swiotlb_bus_to_virt can become static again.
* Need to finish auditing the handful of non-swiotlb users of
is_buffer_dma_capable.
* It might be possible to implement swiolb_dma_mapping_error
and/or swiotlb_dma_supported in terms of dma_map_range.
* Minor detail: it doesn't actually work at the moment ;-)
Ian.
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index 36c0009..026667f 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -174,4 +174,12 @@ dma_cache_sync (struct device *dev, void *vaddr, size_t size,
#define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */
+static inline dma_addr_t dma_map_range(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size)
+{
+ if (addr + size <= mask)
+ return addr;
+ return 0;
+}
+
#endif /* _ASM_IA64_DMA_MAPPING_H */
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 916cbb6..b2813ab 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -309,4 +309,20 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
ops->free_coherent(dev, size, vaddr, bus);
}
+static inline dma_addr_t dma_map_range(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size)
+{
+ dma_addr_t dma_addr;
+#ifdef CONFIG_XEN
+ extern int xen_range_needs_mapping(phys_addr_t paddr, size_t size);
+ if (xen_pv_domain() && xen_range_needs_mapping(addr, size))
+ return 0;
+#endif
+
+ dma_addr = swiotlb_phys_to_bus(dev, addr);
+ if (dma_addr + size <= mask)
+ return 0;
+ return dma_addr;
+}
+
#endif
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 2fffc22..c2b4196 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -145,8 +145,8 @@ again:
if (!page)
return NULL;
- addr = page_to_phys(page);
- if (!is_buffer_dma_capable(dma_mask, addr, size)) {
+ addr = dma_map_range(dev, dma_mask, page_to_phys(page), size);
+ if (!(addr == 0)) {
__free_pages(page, get_order(size));
if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 1e8920d..6a55770 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -191,13 +191,13 @@ static inline int
need_iommu(struct device *dev, unsigned long addr, size_t size)
{
return force_iommu ||
- !is_buffer_dma_capable(*dev->dma_mask, addr, size);
+ dma_map_range(dev, *dev->dma_mask, addr, size) == 0;
}
static inline int
nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
{
- return !is_buffer_dma_capable(*dev->dma_mask, addr, size);
+ return dma_map_range(dev, *dev->dma_mask, addr, size) == 0;
}
/* Map a single continuous physical area into the IOMMU.
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 71d412a..712ce59 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -12,13 +12,13 @@
#include <asm/dma.h>
static int
-check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
+check_addr(char *name, struct device *hwdev, phys_addr_t phys, size_t size)
{
- if (hwdev && !is_buffer_dma_capable(*hwdev->dma_mask, bus, size)) {
+ if (hwdev && dma_map_range(hwdev, *hwdev->dma_mask, phys, size) == 0) {
if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
printk(KERN_ERR
"nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
- name, (long long)bus, size,
+ name, (long long)phys, size,
(long long)*hwdev->dma_mask);
return 0;
}
@@ -30,12 +30,12 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
enum dma_data_direction dir,
struct dma_attrs *attrs)
{
- dma_addr_t bus = page_to_phys(page) + offset;
+ phys_addr_t phys = page_to_phys(page) + offset;
WARN_ON(size == 0);
- if (!check_addr("map_single", dev, bus, size))
+ if (!check_addr("map_single", dev, phys, size))
return bad_dma_address;
flush_write_buffers();
- return bus;
+ return phys;
}
/* Map a set of buffers described by scatterlist in streaming
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8083b6a..85dafa1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -96,11 +96,6 @@ static inline int is_device_dma_capable(struct device *dev)
return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
}
-static inline int is_buffer_dma_capable(u64 mask, dma_addr_t addr, size_t size)
-{
- return addr + size <= mask;
-}
-
#ifdef CONFIG_HAS_DMA
#include <asm/dma-mapping.h>
#else
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index cec5f62..4fd5185 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -147,17 +147,6 @@ void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
}
-int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
- dma_addr_t addr, size_t size)
-{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
-}
-
-int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return 0;
-}
-
static void swiotlb_print_info(unsigned long bytes)
{
phys_addr_t pstart, pend;
@@ -318,17 +307,6 @@ cleanup1:
return -ENOMEM;
}
-static inline int
-address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size)
-{
- return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
-}
-
-static inline int range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return swiotlb_force || swiotlb_arch_range_needs_mapping(paddr, size);
-}
-
static int is_swiotlb_buffer(char *addr)
{
return addr >= io_tlb_start && addr < io_tlb_end;
@@ -555,18 +533,17 @@ void *
swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags)
{
- dma_addr_t dev_addr;
+ phys_addr_t phys;
void *ret;
int order = get_order(size);
u64 dma_mask = DMA_BIT_MASK(32);
+ dma_addr_t dma_addr;
if (hwdev && hwdev->coherent_dma_mask)
dma_mask = hwdev->coherent_dma_mask;
ret = (void *)__get_free_pages(flags, order);
- if (ret &&
- !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(hwdev, ret),
- size)) {
+ if (ret && dma_map_range(hwdev, dma_mask, virt_to_phys(ret), size) == 0) {
/*
* The allocated memory isn't reachable by the device.
*/
@@ -585,19 +562,20 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
}
memset(ret, 0, size);
- dev_addr = swiotlb_virt_to_bus(hwdev, ret);
+ phys = virt_to_phys(ret);
/* Confirm address can be DMA'd by device */
- if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
- printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+ dma_addr = dma_map_range(hwdev, dma_mask, phys, size);
+ if (dma_addr == 0) {
+ printk("hwdev DMA mask = 0x%016Lx, physical addr = 0x%016Lx\n",
(unsigned long long)dma_mask,
- (unsigned long long)dev_addr);
+ (unsigned long long)phys);
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
do_unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
return NULL;
}
- *dma_handle = dev_addr;
+ *dma_handle = dma_addr;
return ret;
}
EXPORT_SYMBOL(swiotlb_alloc_coherent);
@@ -649,7 +627,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = swiotlb_phys_to_bus(dev, phys);
+ dma_addr_t dma_addr;
void *map;
BUG_ON(dir == DMA_NONE);
@@ -658,9 +636,9 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
- if (!address_needs_mapping(dev, dev_addr, size) &&
- !range_needs_mapping(phys, size))
- return dev_addr;
+ dma_addr = dma_map_range(dev, dma_get_mask(dev), phys, size);
+ if (dma_addr && !swiotlb_force)
+ return dma_addr;
/*
* Oh well, have to allocate and map a bounce buffer.
@@ -671,15 +649,14 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
map = io_tlb_overflow_buffer;
}
- dev_addr = swiotlb_virt_to_bus(dev, map);
-
/*
* Ensure that the address returned is DMA'ble
*/
- if (address_needs_mapping(dev, dev_addr, size))
+ dma_addr = dma_map_range(dev, dma_get_mask(dev), virt_to_phys(map), size);
+ if (dma_addr == 0)
panic("map_single: bounce buffer is not DMA'ble");
- return dev_addr;
+ return dma_addr;
}
EXPORT_SYMBOL_GPL(swiotlb_map_page);
@@ -820,10 +797,8 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
for_each_sg(sgl, sg, nelems, i) {
phys_addr_t paddr = sg_phys(sg);
- dma_addr_t dev_addr = swiotlb_phys_to_bus(hwdev, paddr);
-
- if (range_needs_mapping(paddr, sg->length) ||
- address_needs_mapping(hwdev, dev_addr, sg->length)) {
+ dma_addr_t dma_addr = dma_map_range(hwdev, dma_get_mask(hwdev), paddr, sg->length);
+ if (dma_addr == 0 || swiotlb_force) {
void *map = map_single(hwdev, sg_phys(sg),
sg->length, dir);
if (!map) {
@@ -835,9 +810,9 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
sgl[0].dma_length = 0;
return 0;
}
- sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
- } else
- sg->dma_address = dev_addr;
+ dma_addr = dma_map_range(hwdev, dma_get_mask(hwdev), virt_to_phys(map), sg->length);
+ }
+ sg->dma_address = dma_addr;
sg->dma_length = sg->length;
}
return nelems;
^ permalink raw reply related
* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: FUJITA Tomonori @ 2009-05-22 10:51 UTC (permalink / raw)
To: jeremy; +Cc: fujita.tomonori, linuxppc-dev, linux-kernel, Ian.Campbell
In-Reply-To: <4A15B72E.2070202@goop.org>
On Thu, 21 May 2009 13:18:54 -0700
Jeremy Fitzhardinge <jeremy@goop.org> wrote:
> Becky Bruce wrote:
> > I can work with that, but it's going to be a bit inefficient, as I
> > actually need the dma_addr_t, not the phys_addr_t, so I'll have to
> > convert. In every case, this is a conversion I've already done and
> > that I need in the calling code as well. Can we pass in both the
> > phys_addr_t and the dma_addr_t?
>
> The Xen implementation would needs to do the phys to bus conversion page
> by page anyway, so it wouldn't help much. But it also wouldn't hurt.
>
> How expensive is the phys-to-bus conversion on power? Is it worth
> making the interface more complex for? Would passing phys+bus mean that
> we wouldn't also need to pass dev?
I don't think so. POWERPC needs it.
^ permalink raw reply
* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: FUJITA Tomonori @ 2009-05-22 10:51 UTC (permalink / raw)
To: Ian.Campbell; +Cc: fujita.tomonori, linuxppc-dev, jeremy, linux-kernel
In-Reply-To: <1242932497.25553.230.camel@localhost.localdomain>
On Thu, 21 May 2009 20:01:37 +0100
Ian Campbell <Ian.Campbell@eu.citrix.com> wrote:
> > It's not actually clear to me that we need that check, though. Can
> > someone explain what case that was designed to catch?
>
> If map_single fails and returns NULL then we try to use
> io_tlb_overflow_buffer, if that is somehow not DMA-able (for the
> particular device) then the check will trigger. I would have thought we
> could arrange that the overflow buffer is always OK and really if
> map_page is failing we must be close the edge already.
And iotlb buffers are not guaranteed to be DMA-capable; it's possible
that some drivers (with poor dma address restrictions) can't handle
some part of iotlb buffers.
So after allocating some ioblb buffer, we need to check if the buffers
are DMA-capable for a driver. Well, it's unlikely though.
Well, it would be better to move the check to map_single().
^ permalink raw reply
* [GIT PULL] fsldma driver fixes
From: Li Yang @ 2009-05-22 10:47 UTC (permalink / raw)
To: Dan Williams; +Cc: linuxppc-dev Development, lkml
Hi Dan,
Here are fixes for Freescale DMA engine driver.
Thanks,
- Leo
The following changes since commit 5805977e63a36ad56594a623f3bd2bebcb7db233:
Linus Torvalds (1):
Merge branch 'for-linus' of git://git.kernel.org/.../jbarnes/drm-2.6
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/leo/fsl-soc.git fsldma
Ira Snyder (4):
fsldma: fix "DMA halt timeout!" errors
fsldma: fix infinite loop on multi-descriptor DMA chain completion
fsldma: snooping is not enabled for last entry in descriptor chain
fsldma: fix memory leak on error path in fsl_dma_prep_memcpy()
Li Yang (1):
fsldma: update mailling list address in MAINTAINERS
Roel Kluin (1):
fsldma: fix check on potential fdev->chan[] overflow
MAINTAINERS | 2 +-
drivers/dma/fsldma.c | 58 ++++++++++++++++++++++++++++++++++---------------
2 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2b349ba..cac3e3b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2241,7 +2241,7 @@ P: Li Yang
M: leoli@freescale.com
P: Zhang Wei
M: zw@zh-kernel.org
-L: linuxppc-embedded@ozlabs.org
+L: linuxppc-dev@ozlabs.org
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/dma/fsldma.*
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index da8a8ed..1578310 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -179,9 +179,14 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan)
static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
struct fsl_desc_sw *desc)
{
+ u64 snoop_bits;
+
+ snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+ ? FSL_DMA_SNEN : 0;
+
desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
- DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL,
- 64);
+ DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+ | snoop_bits, 64);
}
static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
@@ -313,8 +318,8 @@ static void fsl_chan_toggle_ext_start(struct
fsl_dma_chan *fsl_chan, int enable)
static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
{
- struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+ struct fsl_desc_sw *desc;
unsigned long flags;
dma_cookie_t cookie;
@@ -322,14 +327,17 @@ static dma_cookie_t fsl_dma_tx_submit(struct
dma_async_tx_descriptor *tx)
spin_lock_irqsave(&fsl_chan->desc_lock, flags);
cookie = fsl_chan->common.cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- desc->async_tx.cookie = cookie;
- fsl_chan->common.cookie = desc->async_tx.cookie;
+ list_for_each_entry(desc, &tx->tx_list, node) {
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
- append_ld_queue(fsl_chan, desc);
- list_splice_init(&desc->async_tx.tx_list, fsl_chan->ld_queue.prev);
+ desc->async_tx.cookie = cookie;
+ }
+
+ fsl_chan->common.cookie = cookie;
+ append_ld_queue(fsl_chan, tx_to_fsl_desc(tx));
+ list_splice_init(&tx->tx_list, fsl_chan->ld_queue.prev);
spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
@@ -454,8 +462,8 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
{
struct fsl_dma_chan *fsl_chan;
struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
+ struct list_head *list;
size_t copy;
- LIST_HEAD(link_chain);
if (!chan)
return NULL;
@@ -472,7 +480,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
if (!new) {
dev_err(fsl_chan->dev,
"No free memory for link descriptor\n");
- return NULL;
+ goto fail;
}
#ifdef FSL_DMA_LD_DEBUG
dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
@@ -507,7 +515,19 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
/* Set End-of-link to the last link descriptor of new list*/
set_ld_eol(fsl_chan, new);
- return first ? &first->async_tx : NULL;
+ return &first->async_tx;
+
+fail:
+ if (!first)
+ return NULL;
+
+ list = &first->async_tx.tx_list;
+ list_for_each_entry_safe_reverse(new, prev, list, node) {
+ list_del(&new->node);
+ dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
+ }
+
+ return NULL;
}
/**
@@ -598,15 +618,16 @@ static void fsl_chan_xfer_ld_queue(struct
fsl_dma_chan *fsl_chan)
dma_addr_t next_dest_addr;
unsigned long flags;
+ spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+
if (!dma_is_idle(fsl_chan))
- return;
+ goto out_unlock;
dma_halt(fsl_chan);
/* If there are some link descriptors
* not transfered in queue. We need to start it.
*/
- spin_lock_irqsave(&fsl_chan->desc_lock, flags);
/* Find the first un-transfer desciptor */
for (ld_node = fsl_chan->ld_queue.next;
@@ -617,8 +638,6 @@ static void fsl_chan_xfer_ld_queue(struct
fsl_dma_chan *fsl_chan)
fsl_chan->common.cookie) == DMA_SUCCESS);
ld_node = ld_node->next);
- spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-
if (ld_node != &fsl_chan->ld_queue) {
/* Get the ld start address from ld_queue */
next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
@@ -630,6 +649,9 @@ static void fsl_chan_xfer_ld_queue(struct
fsl_dma_chan *fsl_chan)
set_cdar(fsl_chan, 0);
set_ndar(fsl_chan, 0);
}
+
+out_unlock:
+ spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
}
/**
@@ -830,7 +852,7 @@ static int __devinit fsl_dma_chan_probe(struct
fsl_dma_device *fdev,
new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
- if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) {
+ if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
dev_err(fdev->dev, "There is no %d channel!\n",
new_fsl_chan->id);
err = -EINVAL;
^ permalink raw reply related
* Re: [PATCH] fsldma: fix memory leak on error path in fsl_dma_prep_memcpy()
From: Li Yang @ 2009-05-22 10:30 UTC (permalink / raw)
To: Ira Snyder; +Cc: linuxppc-dev, Dan Williams
In-Reply-To: <20090515165946.GA858@ovro.caltech.edu>
On Sat, May 16, 2009 at 12:59 AM, Ira Snyder <iws@ovro.caltech.edu> wrote:
> When preparing a memcpy operation, if the kernel fails to allocate memory
> for a link descriptor after the first link descriptor has already been
> allocated, then some memory will never be released. Fix the problem by
> walking the list of allocated descriptors backwards, and freeing the
> allocated descriptors back into the DMA pool.
>
> Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
Applied the following patches:
fsldma: fix "DMA halt timeout!" errors
fsldma: fix infinite loop on multi-descriptor DMA chain completion
fsldma: snooping is not enabled for last entry in descriptor chain
fsldma: fix memory leak on error path in fsl_dma_prep_memcpy()
Thanks
- Leo
^ permalink raw reply
* Re: can't flush tlb on e500
From: Benjamin Herrenschmidt @ 2009-05-22 9:42 UTC (permalink / raw)
To: Saito Hideo; +Cc: linuxppc-dev list, linux-kernel, Kumar Gala
In-Reply-To: <1242984470.26104.29.camel@pasglop>
On Fri, 2009-05-22 at 19:27 +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2009-05-20 at 19:12 +0900, Saito Hideo wrote:
>
> > I think that the tlb should be cleared before mm->context.id is set
> > MMU_NO_CONTEXT.
>
> You are right, this definitely looks like a bug on platforms that have
> HW support for the tlbil instruction (and thus care about the PID for
> flushing) which afaik is only the case of recent freescale chips.
In fact, you are doubly right in that it also happens on other platforms
because local_flush_tlb_mm() will check if the PID is MMU_NO_CONTEXT
regardless of what tlbilx supports.. oops
Looks like I only ran my context torture test with CONFIG_SMP enabled.
Shame on me.
> Have you verified that this change fixes your problem ?
>
> Can you re-submit to linuxppc-dev@ozlabs.org mailing list, along with
> proper changeset comment and signed-off-by: line ?
>
> Cheers,
> Ben.
>
> > --- arch/powerpc/mm/mmu_context_nohash.c.orig 2009-03-24
> > 08:12:14.000000000 +0900
> > +++ arch/powerpc/mm/mmu_context_nohash.c 2009-05-20 18:33:53.000000000 +0900
> > @@ -122,22 +122,22 @@ static unsigned int steal_context_up(uns
> > struct mm_struct *mm;
> > int cpu = smp_processor_id();
> >
> > /* Pick up the victim mm */
> > mm = context_mm[id];
> >
> > pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm);
> >
> > - /* Mark this mm has having no context anymore */
> > - mm->context.id = MMU_NO_CONTEXT;
> > -
> > /* Flush the TLB for that context */
> > local_flush_tlb_mm(mm);
> >
> > + /* Mark this mm has having no context anymore */
> > + mm->context.id = MMU_NO_CONTEXT;
> > +
> > /* XXX This clear should ultimately be part of local_flush_tlb_mm */
> > __clear_bit(id, stale_map[cpu]);
> >
> > return id;
> > }
> >
> > #ifdef DEBUG_MAP_CONSISTENCY
> > static void context_check_map(void)
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at http://www.tux.org/lkml/
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: can't flush tlb on e500
From: Benjamin Herrenschmidt @ 2009-05-22 9:27 UTC (permalink / raw)
To: Saito Hideo; +Cc: linuxppc-dev list, linux-kernel, Kumar Gala
In-Reply-To: <d50492d40905200312r729608a3nf244b153892ac257@mail.gmail.com>
On Wed, 2009-05-20 at 19:12 +0900, Saito Hideo wrote:
> I think that the tlb should be cleared before mm->context.id is set
> MMU_NO_CONTEXT.
You are right, this definitely looks like a bug on platforms that have
HW support for the tlbil instruction (and thus care about the PID for
flushing) which afaik is only the case of recent freescale chips.
Have you verified that this change fixes your problem ?
Can you re-submit to linuxppc-dev@ozlabs.org mailing list, along with
proper changeset comment and signed-off-by: line ?
Cheers,
Ben.
> --- arch/powerpc/mm/mmu_context_nohash.c.orig 2009-03-24
> 08:12:14.000000000 +0900
> +++ arch/powerpc/mm/mmu_context_nohash.c 2009-05-20 18:33:53.000000000 +0900
> @@ -122,22 +122,22 @@ static unsigned int steal_context_up(uns
> struct mm_struct *mm;
> int cpu = smp_processor_id();
>
> /* Pick up the victim mm */
> mm = context_mm[id];
>
> pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm);
>
> - /* Mark this mm has having no context anymore */
> - mm->context.id = MMU_NO_CONTEXT;
> -
> /* Flush the TLB for that context */
> local_flush_tlb_mm(mm);
>
> + /* Mark this mm has having no context anymore */
> + mm->context.id = MMU_NO_CONTEXT;
> +
> /* XXX This clear should ultimately be part of local_flush_tlb_mm */
> __clear_bit(id, stale_map[cpu]);
>
> return id;
> }
>
> #ifdef DEBUG_MAP_CONSISTENCY
> static void context_check_map(void)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* to access web server on PowerPC from system outside the local network
From: patel rajendra @ 2009-05-22 8:10 UTC (permalink / raw)
To: linuxppc-dev list
[-- Attachment #1: Type: text/plain, Size: 390 bytes --]
Hi,
I have made web server on PowerPC and it runs nicely. Currently it is on internal network.
I want to access it from any system outside the local network.
Can any one let me know what is the procedure for that?
Thanks for your time....
Raj
Cricket on your mind? Visit the ultimate cricket website. Enter http://beta.cricket.yahoo.com
[-- Attachment #2: Type: text/html, Size: 624 bytes --]
^ permalink raw reply
* Re: [PATCH] freescale: beyond ARRAY_SIZE of fdev->chan
From: Li Yang @ 2009-05-22 8:03 UTC (permalink / raw)
To: Roel Kluin; +Cc: linuxppc-dev, Andrew Morton, lkml
In-Reply-To: <4A133DEF.6080604@gmail.com>
On Wed, May 20, 2009 at 7:17 AM, Roel Kluin <roel.kluin@gmail.com> wrote:
> Do not go beyond ARRAY_SIZE of fdev->chan
>
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Indeed, thanks.
But I would like the title and description of this patch be changed to
like this:
fsldma: fix check on potential fdev->chan[] overflow
Fix the check of potential array overflow when using corrupted channel
device tree nodes.
> ---
> diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
> index da8a8ed..391b1bd 100644
> --- a/drivers/dma/fsldma.c
> +++ b/drivers/dma/fsldma.c
> @@ -830,7 +830,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dm=
a_device *fdev,
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0new_fsl_chan->id =3D ((new_fsl_chan->reg.start=
- 0x100) & 0xfff) >> 7;
> - =C2=A0 =C2=A0 =C2=A0 if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVIC=
E) {
> + =C2=A0 =C2=A0 =C2=A0 if (new_fsl_chan->id >=3D FSL_DMA_MAX_CHANS_PER_DE=
VICE) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(fdev->dev,=
"There is no %d channel!\n",
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0new_fsl_chan->id);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D -EINVAL;
^ permalink raw reply
* Re: [net-next-2.6 PATCH] can: SJA1000: generic OF platform bus driver
From: David Miller @ 2009-05-22 6:31 UTC (permalink / raw)
To: grant.likely; +Cc: netdev, devicetree-discuss, Linuxppc-dev
In-Reply-To: <fa686aa40905212142n4a8c3caamb2f28eef036e3922@mail.gmail.com>
From: Grant Likely <grant.likely@secretlab.ca>
Date: Thu, 21 May 2009 22:42:07 -0600
> On Wed, May 20, 2009 at 11:06 AM, Wolfgang Grandegger <wg@grandegger.=
com> wrote:
>> This patch adds a generic driver for SJA1000 chips on the OpenFirmwa=
re
>> platform bus found on embedded PowerPC systems. You need a SJA1000 n=
ode
>> definition in your flattened device tree source (DTS) file similar t=
o:
>>
>> =A0 can@3,100 {
>> =A0 =A0 =A0 =A0 =A0 compatible =3D "philips,sja1000";
>> =A0 =A0 =A0 =A0 =A0 reg =3D <3 0x100 0x80>;
>> =A0 =A0 =A0 =A0 =A0 clock-frequency =3D <8000000>;
>> =A0 =A0 =A0 =A0 =A0 cdr-reg =3D <0x48>;
>> =A0 =A0 =A0 =A0 =A0 ocr-reg =3D <0x0a>;
>> =A0 =A0 =A0 =A0 =A0 interrupts =3D <2 0>;
>> =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&mpic>;
>> =A0 };
> =
> This new binding must be documented in Documentation/powerpc/dts-bind=
ings
Wolfgang, please add this documentation and resubmit your patch.
Thanks!
^ permalink raw reply
* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2009-05-22 6:11 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list
Hi Linus !
Here's a small fix for .30 that works around a regression caused by
enabling MSI support in the IPR driver.
Cheers,
Ben.
The following changes since commit 5805977e63a36ad56594a623f3bd2bebcb7db233:
Linus Torvalds (1):
Merge branch 'for-linus' of git://git.kernel.org/.../jbarnes/drm-2.6
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge
Michael Ellerman (1):
powerpc/maple: Add a quirk to disable MSI for IPR on Bimini
arch/powerpc/platforms/maple/pci.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
^ permalink raw reply
* Re: [PATCH] powerpc/maple: Add a quirk to disable MSI for IPR on Bimini
From: Benjamin Herrenschmidt @ 2009-05-22 5:57 UTC (permalink / raw)
To: Michael Ellerman; +Cc: James.Bottomley, linuxppc-dev, brking, wayneb
In-Reply-To: <ddac4814a020b7d4248834f846d7a7afe1ce1567.1242968955.git.michael@ellerman.id.au>
On Fri, 2009-05-22 at 15:10 +1000, Michael Ellerman wrote:
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/platforms/maple/pci.c | 14 ++++++++++++++
> 1 files changed, 14 insertions(+), 0 deletions(-)
>
>
> It's getting late in the cycle, so until we can work out what's wrong
> with IPR + MSI on Bimini, add a quirk to disable MSI for IPR.
Thanks, I'll send that to Linus for 2.6.30
Cheers,
Ben.
> diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
> index 3018552..04296ff 100644
> --- a/arch/powerpc/platforms/maple/pci.c
> +++ b/arch/powerpc/platforms/maple/pci.c
> @@ -592,3 +592,17 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
> }
> return irq;
> }
> +
> +static void __devinit quirk_ipr_msi(struct pci_dev *dev)
> +{
> + /* Something prevents MSIs from the IPR from working on Bimini,
> + * and the driver has no smarts to recover. So disable MSI
> + * on it for now. */
> +
> + if (machine_is(maple)) {
> + dev->no_msi = 1;
> + dev_info(&dev->dev, "Quirk disabled MSI\n");
> + }
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
> + quirk_ipr_msi);
^ permalink raw reply
* Re: problem in registering the device while inserting the kernel module
From: Grant Likely @ 2009-05-22 5:25 UTC (permalink / raw)
To: patel rajendra; +Cc: linuxppc-dev
In-Reply-To: <601801.28414.qm@web94805.mail.in2.yahoo.com>
On Thu, May 21, 2009 at 12:20 AM, patel rajendra <rdpatel55@yahoo.co.in> wrote:
> Hi Members of linuxppc,
>
> I'm working on XUPV2P board with Virtex II Pro FPGA device.
>
> I written a kernel module for LED device. I got that module run successfuly
> on ML403 board having Virtex 4 FPGA.I have not make any change in my source
> code for XUP board, because I don't feel any change is required.
What kernel version are you using?
Are you using arch/ppc or arch/powerpc?
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH] powerpc/maple: Add a quirk to disable MSI for IPR on Bimini
From: Michael Ellerman @ 2009-05-22 5:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: James.Bottomley, brking, wayneb
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/maple/pci.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
It's getting late in the cycle, so until we can work out what's wrong
with IPR + MSI on Bimini, add a quirk to disable MSI for IPR.
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 3018552..04296ff 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -592,3 +592,17 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
}
return irq;
}
+
+static void __devinit quirk_ipr_msi(struct pci_dev *dev)
+{
+ /* Something prevents MSIs from the IPR from working on Bimini,
+ * and the driver has no smarts to recover. So disable MSI
+ * on it for now. */
+
+ if (machine_is(maple)) {
+ dev->no_msi = 1;
+ dev_info(&dev->dev, "Quirk disabled MSI\n");
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
+ quirk_ipr_msi);
--
1.6.2.1
^ permalink raw reply related
* Re: [PATCH] mpc52xx_psc_spi: Convert to cs_control callback
From: Grant Likely @ 2009-05-22 5:07 UTC (permalink / raw)
To: Anton Vorontsov
Cc: linuxppc-dev, Andrew Morton, David Brownell, spi-devel-general
In-Reply-To: <20090430223114.GA12571@oksana.dev.rtsoft.ru>
On Thu, Apr 30, 2009 at 4:31 PM, Anton Vorontsov
<avorontsov@ru.mvista.com> wrote:
> mpc52xx_psc_spi driver is the last user of the legacy activate_cs
> and deactivate_cs callbacks, so convert the driver to the cs_control
> hook and remove the legacy callbacks from fsl_spi_platform_data
> struct.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
David, will you pick this one up, or can I put it into Ben's powerpc
-next tree (since it is a powerpc-only device driver).
g.
> ---
> =A0drivers/spi/mpc52xx_psc_spi.c | =A0 22 +++++++++-------------
> =A0include/linux/fsl_devices.h =A0 | =A0 =A04 ----
> =A02 files changed, 9 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.=
c
> index 68c77a9..e1901fd 100644
> --- a/drivers/spi/mpc52xx_psc_spi.c
> +++ b/drivers/spi/mpc52xx_psc_spi.c
> @@ -13,6 +13,7 @@
>
> =A0#include <linux/module.h>
> =A0#include <linux/init.h>
> +#include <linux/types.h>
> =A0#include <linux/errno.h>
> =A0#include <linux/interrupt.h>
> =A0#include <linux/of_platform.h>
> @@ -30,8 +31,7 @@
>
> =A0struct mpc52xx_psc_spi {
> =A0 =A0 =A0 =A0/* fsl_spi_platform data */
> - =A0 =A0 =A0 void (*activate_cs)(u8, u8);
> - =A0 =A0 =A0 void (*deactivate_cs)(u8, u8);
> + =A0 =A0 =A0 void (*cs_control)(struct spi_device *spi, bool on);
> =A0 =A0 =A0 =A0u32 sysclk;
>
> =A0 =A0 =A0 =A0/* driver internal data */
> @@ -111,18 +111,16 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_=
device *spi)
> =A0 =A0 =A0 =A0out_be16((u16 __iomem *)&psc->ccr, ccr);
> =A0 =A0 =A0 =A0mps->bits_per_word =3D cs->bits_per_word;
>
> - =A0 =A0 =A0 if (mps->activate_cs)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs(spi->chip_select,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (spi->mode =
& SPI_CS_HIGH) ? 1 : 0);
> + =A0 =A0 =A0 if (mps->cs_control)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control(spi, (spi->mode & SPI_CS_HI=
GH) ? 1 : 0);
> =A0}
>
> =A0static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
> =A0{
> =A0 =A0 =A0 =A0struct mpc52xx_psc_spi *mps =3D spi_master_get_devdata(spi=
->master);
>
> - =A0 =A0 =A0 if (mps->deactivate_cs)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs(spi->chip_select,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (spi->mode =
& SPI_CS_HIGH) ? 1 : 0);
> + =A0 =A0 =A0 if (mps->cs_control)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control(spi, (spi->mode & SPI_CS_HI=
GH) ? 0 : 1);
> =A0}
>
> =A0#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
> @@ -388,15 +386,13 @@ static int __init mpc52xx_psc_spi_do_probe(struct d=
evice *dev, u32 regaddr,
> =A0 =A0 =A0 =A0mps->irq =3D irq;
> =A0 =A0 =A0 =A0if (pdata =3D=3D NULL) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_warn(dev, "probe called without platfo=
rm data, no "
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "(de)activa=
te_cs function will be called\n");
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs =3D NULL;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs =3D NULL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "cs_control=
function will be called\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control =3D NULL;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mps->sysclk =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->bus_num =3D bus_num;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->num_chipselect =3D 255;
> =A0 =A0 =A0 =A0} else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs =3D pdata->activate_cs;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs =3D pdata->deactivate_cs=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control =3D pdata->cs_control;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mps->sysclk =3D pdata->sysclk;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->bus_num =3D pdata->bus_num;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->num_chipselect =3D pdata->max_chip=
select;
> diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
> index 244677c..43fc95d 100644
> --- a/include/linux/fsl_devices.h
> +++ b/include/linux/fsl_devices.h
> @@ -79,10 +79,6 @@ struct fsl_spi_platform_data {
> =A0 =A0 =A0 =A0u16 =A0 =A0 max_chipselect;
> =A0 =A0 =A0 =A0void =A0 =A0(*cs_control)(struct spi_device *spi, bool on)=
;
> =A0 =A0 =A0 =A0u32 =A0 =A0 sysclk;
> -
> - =A0 =A0 =A0 /* Legacy hooks, used by mpc52xx_psc_spi driver. */
> - =A0 =A0 =A0 void =A0 =A0(*activate_cs)(u8 cs, u8 polarity);
> - =A0 =A0 =A0 void =A0 =A0(*deactivate_cs)(u8 cs, u8 polarity);
> =A0};
>
> =A0struct mpc8xx_pcmcia_ops {
> --
> 1.6.2.2
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [net-next-2.6 PATCH] can: SJA1000: generic OF platform bus driver
From: Grant Likely @ 2009-05-22 4:42 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Linux Netdev List, devicetree-discuss, linuxppc-dev
In-Reply-To: <4A143896.7050200@grandegger.com>
On Wed, May 20, 2009 at 11:06 AM, Wolfgang Grandegger <wg@grandegger.com> w=
rote:
> This patch adds a generic driver for SJA1000 chips on the OpenFirmware
> platform bus found on embedded PowerPC systems. You need a SJA1000 node
> definition in your flattened device tree source (DTS) file similar to:
>
> =A0 can@3,100 {
> =A0 =A0 =A0 =A0 =A0 compatible =3D "philips,sja1000";
> =A0 =A0 =A0 =A0 =A0 reg =3D <3 0x100 0x80>;
> =A0 =A0 =A0 =A0 =A0 clock-frequency =3D <8000000>;
> =A0 =A0 =A0 =A0 =A0 cdr-reg =3D <0x48>;
> =A0 =A0 =A0 =A0 =A0 ocr-reg =3D <0x0a>;
> =A0 =A0 =A0 =A0 =A0 interrupts =3D <2 0>;
> =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&mpic>;
> =A0 };
This new binding must be documented in Documentation/powerpc/dts-bindings
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: Audio and mpc5200 bestcomm tasks
From: Grant Likely @ 2009-05-22 4:33 UTC (permalink / raw)
To: Jon Smirl; +Cc: linuxppc-dev
In-Reply-To: <9e4733910905211152x6ded5c9tadc085bc4bc800e3@mail.gmail.com>
On Thu, May 21, 2009 at 12:52 PM, Jon Smirl <jonsmirl@gmail.com> wrote:
> ALSA really wants to dynamically know the address of the current DMA
> location while transfers are active. This is an important piece of
> implementing pause/resume. Pause doesn't work too well if there is 2s
> of music already queued. The work around is to know the sample rate
> and use the jiffy count to estimate how far into the buffer DMA has
> progressed. But that's not as accurate as just asking the DMA
> hardware.
>
> I poked around in the SRAM data and couldn't find the address. Is it
> there or can the Bestcomm tasks be modified to leave it somewhere
> visible?
It may be possible, but I haven't made any attempts at writing
bestcomm task code. I've got no idea how difficult it would be.
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 1/1] Remove __devinit annotation from pcibios_claim_one_bus()
From: Tony Breeds @ 2009-05-22 3:32 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
pcibios_finish_adding_to_bus() is NOT annotated __devinit but it calls
pcibios_claim_one_bus(). pcibios_finish_adding_to_bus() is called from
at least the rpadlpar code which also is NOT annotated __devinit.
The annotation seems bogus so remove it.
Found by Jeremy Huddleston a reported at:
http://bugzilla.kernel.org/show_bug.cgi?id=13228
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/kernel/pci-common.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0f41812..a9f988f 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1469,7 +1469,7 @@ void __init pcibios_resource_survey(void)
* rest of the code later, for now, keep it as-is as our main
* resource allocation function doesn't deal with sub-trees yet.
*/
-void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+void pcibios_claim_one_bus(struct pci_bus *bus)
{
struct pci_dev *dev;
struct pci_bus *child_bus;
--
1.6.0.6
^ permalink raw reply related
* Re: question : DMA of PCI bridge
From: Sauce.Cheng @ 2009-05-22 3:24 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <4A14D12D.4050302@ovro.caltech.edu>
>
> in the manual reference charpter 9.13 DMA, source and destination address
> If you are DMAing from an internal peripheral, then it's
> width will be hard-coded and can be read from the user-manual.
you mean it will be set by hard circuit ? maybe i should talk with your hard
engineer.
but as you say, the width will be hard-coded, mean that the width can not be
changed ?
it can fetch 16 bits to 32bits, can not tetch 16bits to 16bits ?
i am sorry about my poor English, i am not sure if i expressed clearly
> If you are DMAing from a local bus then the local bus definition
> should determine what happens. For example, on the MPC8349, you
> can put 16-bit flash on the local bus, and configure the local
> bus controller to know that it is 16-bits wide. A 32-bit access
> by the CPU or DMA controller will generate two reads on the
> local bus.
that's right, BRx and ORx should be configured for setting width, but that
is bus width, not data width. or bus width should be equal to data width
what fetch from the bus ?
> You can investigate to see whether the MPC8247 works similarly.
all right, i will , thanks a lot
--
View this message in context: http://www.nabble.com/question-%3A-DMA-of-PCI-bridge-tp23628338p23663840.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* linux-next: powerpc tree build warning
From: Stephen Rothwell @ 2009-05-22 1:28 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-kernel, linuxppc-dev, linux-next, Paul Mackerras,
Vinay Sridhar
[-- Attachment #1: Type: text/plain, Size: 592 bytes --]
Hi Ben,
Today's linux-next build (powerpc ppc64_defconfig) produced this warning:
arch/powerpc/xmon/xmon.c: In function 'dump_log_buf':
arch/powerpc/xmon/xmon.c:2133: warning: unused variable 'i'
Introduced by commit f312deb4cd0c88196edf6dab192b7d42514398d6
("powerpc/xmon: Add dl command to dump contents of __log_buf").
[As an aside, that commit contains this:
Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
but we use real email addresses normally]
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* linux-next: powerpc tree build warning
From: Stephen Rothwell @ 2009-05-22 1:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Arnd Bergmann, linux-kernel, linuxppc-dev, linux-next,
Paul Mackerras, Jan Blunck
[-- Attachment #1: Type: text/plain, Size: 494 bytes --]
Hi Ben,
Today's linux-next build (powerpc ppc64_defconfig) produced this warning:
arch/powerpc/platforms/cell/spufs/inode.c: In function 'spufs_create':
arch/powerpc/platforms/cell/spufs/inode.c:647: warning: label 'out_dput' defined but not used
Introduced by commit 45db9240890d9343c934db1fe82d6e68ac2d28da
("powerpc/spufs: Remove double check for non-negative dentry").
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc:beyond ARRAY_SIZE of args.args
From: Paul Mackerras @ 2009-05-21 23:10 UTC (permalink / raw)
To: Roel Kluin; +Cc: linuxppc-dev, Andrew Morton, paulmck
In-Reply-To: <4A15AF33.60100@gmail.com>
Roel Kluin writes:
> Do not go beyond ARRAY_SIZE of args.args
>
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
> ---
> I'm quite sure the first is correct, but should maybe `args.nret'
> and `nargs + args.nret' also be `>= ARRAY_SIZE(args.args)'?
I don't think this change is needed, and it changes a user-visible
API, so I'm nacking it unless you can convince me there's really a
problem.
If nargs == ARRAY_SIZE(args.args), then args.nret must be zero, so
nothing will access *(args.rets).
Paul.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox