LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc/pci: Remove duplicate check in pcibios_fixup_bus()
From: Gavin Shan @ 2013-07-31  8:43 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

pci_read_bridge_bases() already checks if the PCI bus is root
bus or not, so we needn't do same check in pcibios_fixup_bus()
and just remove it.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/pci-common.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7d22a67..c55fb35 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1055,8 +1055,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 	 * bases. This is -not- called when generating the PCI tree from
 	 * the OF device-tree.
 	 */
-	if (bus->self != NULL)
-		pci_read_bridge_bases(bus);
+	pci_read_bridge_bases(bus);
 
 	/* Now fixup the bus bus */
 	pcibios_setup_bus_self(bus);
-- 
1.7.5.4

^ permalink raw reply related

* Re: [PATCH] powerpc: handle unaligned ldbrx/stdbrx
From: Stephen Rothwell @ 2013-07-31  8:19 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: mikey, paulus, linuxppc-dev
In-Reply-To: <20130731150521.74eb6639@kryten>

[-- Attachment #1: Type: text/plain, Size: 747 bytes --]

Hi Anton,

On Wed, 31 Jul 2013 15:05:21 +1000 Anton Blanchard <anton@samba.org> wrote:
>
> +++ b/arch/powerpc/kernel/align.c
> @@ -764,6 +764,16 @@ int fix_alignment(struct pt_regs *regs)
>  	nb = aligninfo[instr].len;
>  	flags = aligninfo[instr].flags;
>  
> +	/* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */
> +	if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) {

We have get_xop() in asm/disassemble.h (which is unfortunately not
included by this file) ...

> +		nb = 8;
> +		flags = LD+SW;
> +	} else if (IS_XFORM(instruction) &&
> +		   ((instruction >> 1) & 0x3ff) == 660) {

ditto

/me points at a bike shed :-)
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2 1/2] powerpc: Add smp_generic_cpu_bootable
From: Stephen Rothwell @ 2013-07-31  7:52 UTC (permalink / raw)
  To: Andy Fleming; +Cc: linuxppc-dev
In-Reply-To: <1375140785-9782-1-git-send-email-afleming@freescale.com>

[-- Attachment #1: Type: text/plain, Size: 349 bytes --]

Hi Andy,

On Mon, 29 Jul 2013 18:33:04 -0500 Andy Fleming <afleming@freescale.com> wrote:
>
> +EXPORT_SYMBOL(smp_generic_cpu_bootable);

I am pretty sure that none of the places you are going to use this can be
built as modules, so remove this EXPORT_SYMBOL, please.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH RFC v2 2/5] dma: mpc512x: add support for peripheral transfers
From: Alexander Popov @ 2013-07-31  7:46 UTC (permalink / raw)
  To: Lars-Peter Clausen, linuxppc-dev, devicetree-discuss,
	Alexander Popov, Dan Williams, Vinod Koul, Arnd Bergmann,
	Anatolij Gustschin
In-Reply-To: <20130717104234.GJ7080@book.gsilab.sittig.org>

Hello everyone!

I've just sent v3 of part 1 and 2 of RFC series:
https://patchwork.kernel.org/patch/2836123/
https://patchwork.kernel.org/patch/2836124/


2013/7/17 Gerhard Sittig <gsi@denx.de>:
> OK, so the need for explicit start in software or external
> request by the peripheral remains, but the condition for the
> choice is different. It might become a flag attached to the DMA
> channel, that gets setup in the prep routines (memory and slave
> access each use their own prep calls) and gets evaluated in
> execute.

I made a flag "will_access_peripheral" be set up in the device control callback.


> non-MDDRC channels can get used for memory
> transfers as well, which your description of the the former use
> suggests, when slave support was absent.

I tested v3 on MPC5125 with SCLPC driver (transfers between dev and
mem work fine)
and dmatest module (all 64 DMA channels can perform mem-to-mem transfers).


>> > +   mchan = dma_chan_to_mpc_dma_chan(chan);
>> > +   switch (cmd) {
>> > +   case DMA_TERMINATE_ALL:
>> > +           /* disable channel requests */
>> > +           mdma = dma_chan_to_mpc_dma(chan);
>> > +           out_8(&mdma->regs->dmacerq, chan->chan_id);
>> > +           list_splice_tail_init(&mchan->prepared, &mchan->free);
>> > +           list_splice_tail_init(&mchan->queued, &mchan->free);
>> > +           list_splice_tail_init(&mchan->active, &mchan->free);
>>
>> This probably need locking.
>
> Ah, yes.  It needs to grab the same lock as all the other list
> manipulations in the driver's source.

Fixed that too.

Best regards,
Alexander.

^ permalink raw reply

* [PATCH RFC v3 2/5] dma: mpc512x: add support for peripheral transfers
From: Alexander Popov @ 2013-07-31  7:21 UTC (permalink / raw)
  To: Gerhard Sittig, Vinod Koul, Dan Williams, Lars-Peter Clausen,
	Arnd Bergmann, Anatolij Gustschin
  Cc: linuxppc-dev, linux-kernel

Introduce support for slave s/g transfer preparation and the associated
device control callback in the MPC512x DMA controller driver, which adds
support for data transfers between memory and peripheral I/O to the
previously supported mem-to-mem transfers.

Refuse to prepare chunked transfers (transfers with more than one part)
as long as proper support for scatter/gather is lacking.

Keep MPC8308 operational by always starting transfers from software,
this SoC appears to not have request lines for flow control when
peripherals are involved in transfers.

Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
 drivers/dma/mpc512x_dma.c | 183 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 176 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index b8881de..d96d107 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -2,6 +2,7 @@
  * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
  * Copyright (C) Semihalf 2009
  * Copyright (C) Ilya Yanok, Emcraft Systems 2010
+ * Copyright (C) Alexander Popov, Promcontroller 2013
  *
  * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
  * (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -28,11 +29,6 @@
  * file called COPYING.
  */
 
-/*
- * This is initial version of MPC5121 DMA driver. Only memory to memory
- * transfers are supported (tested using dmatest module).
- */
-
 #include <linux/module.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
@@ -199,6 +195,11 @@ struct mpc_dma_chan {
 	struct mpc_dma_tcd		*tcd;
 	dma_addr_t			tcd_paddr;
 
+	/* Settings for access to peripheral FIFO */
+	int				will_access_peripheral;
+	dma_addr_t			per_paddr;	/* FIFO address */
+	u32				tcd_nunits;
+
 	/* Lock for this structure */
 	spinlock_t			lock;
 };
@@ -264,7 +265,10 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
 
 		prev->tcd->dlast_sga = mdesc->tcd_paddr;
 		prev->tcd->e_sg = 1;
-		mdesc->tcd->start = 1;
+
+		/* software start for mem-to-mem transfers */
+		if (mdma->is_mpc8308 || !mchan->will_access_peripheral)
+			mdesc->tcd->start = 1;
 
 		prev = mdesc;
 	}
@@ -276,7 +280,17 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
 
 	if (first != prev)
 		mdma->tcd[cid].e_sg = 1;
-	out_8(&mdma->regs->dmassrt, cid);
+
+	if (mdma->is_mpc8308) {
+		/* MPC8308, no request lines, software initiated start */
+		out_8(&mdma->regs->dmassrt, cid);
+	} else if (mchan->will_access_peripheral) {
+		/* peripherals involved, use external request line */
+		out_8(&mdma->regs->dmaserq, cid);
+	} else {
+		/* memory to memory transfer, software initiated start */
+		out_8(&mdma->regs->dmassrt, cid);
+	}
 }
 
 /* Handle interrupt on one half of DMA controller (32 channels) */
@@ -649,6 +663,158 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 	return &mdesc->desc;
 }
 
+static struct dma_async_tx_descriptor *mpc_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc = NULL;
+	dma_addr_t per_paddr;
+	u32 tcd_nunits = 0;
+	struct mpc_dma_tcd *tcd;
+	unsigned long iflags;
+	struct scatterlist *sg;
+	size_t len;
+	int iter, i;
+
+	if (!list_empty(&mchan->active))
+		return NULL;
+
+	/* currently there is no proper support for scatter/gather */
+	if (sg_len > 1)
+		return NULL;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		spin_lock_irqsave(&mchan->lock, iflags);
+
+		mdesc = list_first_entry(&mchan->free, struct mpc_dma_desc,
+									node);
+		if (!mdesc) {
+			spin_unlock_irqrestore(&mchan->lock, iflags);
+			/* try to free completed descriptors */
+			mpc_dma_process_completed(mdma);
+			return NULL;
+		}
+
+		list_del(&mdesc->node);
+
+		per_paddr = mchan->per_paddr;
+		tcd_nunits = mchan->tcd_nunits;
+
+		spin_unlock_irqrestore(&mchan->lock, iflags);
+
+		mdesc->error = 0;
+		tcd = mdesc->tcd;
+
+		/* Prepare Transfer Control Descriptor for this transaction */
+		memset(tcd, 0, sizeof(struct mpc_dma_tcd));
+
+		if (!IS_ALIGNED(sg_dma_address(sg), 4))
+			return NULL;
+
+		if (direction == DMA_DEV_TO_MEM) {
+			tcd->saddr = per_paddr;
+			tcd->daddr = sg_dma_address(sg);
+			tcd->soff = 0;
+			tcd->doff = 4;
+		} else if (direction == DMA_MEM_TO_DEV) {
+			tcd->saddr = sg_dma_address(sg);
+			tcd->daddr = per_paddr;
+			tcd->soff = 4;
+			tcd->doff = 0;
+		} else {
+			return NULL;
+		}
+		tcd->ssize = MPC_DMA_TSIZE_4;
+		tcd->dsize = MPC_DMA_TSIZE_4;
+
+		len = sg_dma_len(sg);
+
+		if (tcd_nunits)
+			tcd->nbytes = tcd_nunits * 4;
+		else
+			return NULL;
+
+		if (!IS_ALIGNED(len, tcd->nbytes))
+			return NULL;
+
+		iter = len / tcd->nbytes;
+		if (iter > ((1 << 15) - 1)) {   /* maximum biter */
+			return NULL; /* len is too big */
+		} else {
+			/* citer_linkch contains the high bits of iter */
+			tcd->biter = iter & 0x1ff;
+			tcd->biter_linkch = iter >> 9;
+			tcd->citer = tcd->biter;
+			tcd->citer_linkch = tcd->biter_linkch;
+		}
+
+		tcd->e_sg = 0;
+		tcd->d_req = 1;
+
+		/* Place descriptor in prepared list */
+		spin_lock_irqsave(&mchan->lock, iflags);
+		list_add_tail(&mdesc->node, &mchan->prepared);
+		spin_unlock_irqrestore(&mchan->lock, iflags);
+	}
+
+	return &mdesc->desc;
+}
+
+static int mpc_dma_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+				  unsigned long arg)
+{
+	struct mpc_dma_chan *mchan;
+	struct mpc_dma *mdma;
+	struct dma_slave_config *cfg;
+	unsigned long flags;
+
+	mchan = dma_chan_to_mpc_dma_chan(chan);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		/* disable channel requests */
+		mdma = dma_chan_to_mpc_dma(chan);
+
+		spin_lock_irqsave(&mchan->lock, flags);
+
+		out_8(&mdma->regs->dmacerq, chan->chan_id);
+		list_splice_tail_init(&mchan->prepared, &mchan->free);
+		list_splice_tail_init(&mchan->queued, &mchan->free);
+		list_splice_tail_init(&mchan->active, &mchan->free);
+
+		spin_unlock_irqrestore(&mchan->lock, flags);
+
+		return 0;
+	case DMA_SLAVE_CONFIG:
+		cfg = (void *)arg;
+		if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES &&
+		    cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+			return -EINVAL;
+
+		spin_lock_irqsave(&mchan->lock, flags);
+
+		mchan->will_access_peripheral = 1;
+
+		if (cfg->direction == DMA_DEV_TO_MEM) {
+			mchan->per_paddr = cfg->src_addr;
+			mchan->tcd_nunits = cfg->src_maxburst;
+		} else {
+			mchan->per_paddr = cfg->dst_addr;
+			mchan->tcd_nunits = cfg->dst_maxburst;
+		}
+
+		spin_unlock_irqrestore(&mchan->lock, flags);
+
+		return 0;
+	default:
+		return -ENOSYS;
+	}
+
+	return -EINVAL;
+}
+
 static int mpc_dma_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
@@ -733,9 +899,12 @@ static int mpc_dma_probe(struct platform_device *op)
 	dma->device_issue_pending = mpc_dma_issue_pending;
 	dma->device_tx_status = mpc_dma_tx_status;
 	dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy;
+	dma->device_prep_slave_sg = mpc_dma_prep_slave_sg;
+	dma->device_control = mpc_dma_device_control;
 
 	INIT_LIST_HEAD(&dma->channels);
 	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
+	dma_cap_set(DMA_SLAVE, dma->cap_mask);
 
 	for (i = 0; i < dma->chancnt; i++) {
 		mchan = &mdma->channels[i];
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH RFC v3 1/5] dma: mpc512x: reorder mpc8308 specific instructions
From: Alexander Popov @ 2013-07-31  7:20 UTC (permalink / raw)
  To: Gerhard Sittig, Vinod Koul, Dan Williams, Lars-Peter Clausen,
	Arnd Bergmann, Anatolij Gustschin
  Cc: linuxppc-dev, linux-kernel

From: Gerhard Sittig <gsi@denx.de>

Concentrate the test and the specific code for MPC8308
in the 'if' branch and handle MPC512x in the 'else' branch.

This modification only reorders instructions but doesn't change behaviour.

Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
 drivers/dma/mpc512x_dma.c | 42 +++++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2d95673..b8881de 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -50,9 +50,17 @@
 #define MPC_DMA_DESCRIPTORS	64
 
 /* Macro definitions */
-#define MPC_DMA_CHANNELS	64
 #define MPC_DMA_TCD_OFFSET	0x1000
 
+/*
+ * Maximum channel counts for individual hardware variants
+ * and the maximum channel count over all supported controllers,
+ * used for data structure size
+ */
+#define MPC8308_DMACHAN_MAX	16
+#define MPC512x_DMACHAN_MAX	64
+#define MPC_DMA_CHANNELS	64
+
 /* Arbitration mode of group and channel */
 #define MPC_DMA_DMACR_EDCG	(1 << 31)
 #define MPC_DMA_DMACR_ERGA	(1 << 3)
@@ -716,10 +724,10 @@ static int mpc_dma_probe(struct platform_device *op)
 
 	dma = &mdma->dma;
 	dma->dev = dev;
-	if (!mdma->is_mpc8308)
-		dma->chancnt = MPC_DMA_CHANNELS;
+	if (mdma->is_mpc8308)
+		dma->chancnt = MPC8308_DMACHAN_MAX;
 	else
-		dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
+		dma->chancnt = MPC512x_DMACHAN_MAX;
 	dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
 	dma->device_free_chan_resources = mpc_dma_free_chan_resources;
 	dma->device_issue_pending = mpc_dma_issue_pending;
@@ -753,7 +761,19 @@ static int mpc_dma_probe(struct platform_device *op)
 	 * - Round-robin group arbitration,
 	 * - Round-robin channel arbitration.
 	 */
-	if (!mdma->is_mpc8308) {
+	if (mdma->is_mpc8308) {
+		/* MPC8308 has 16 channels and lacks some registers */
+		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
+
+		/* enable snooping */
+		out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
+		/* Disable error interrupts */
+		out_be32(&mdma->regs->dmaeeil, 0);
+
+		/* Clear interrupts status */
+		out_be32(&mdma->regs->dmaintl, 0xFFFF);
+		out_be32(&mdma->regs->dmaerrl, 0xFFFF);
+	} else {
 		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
 					MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
 
@@ -774,18 +794,6 @@ static int mpc_dma_probe(struct platform_device *op)
 		/* Route interrupts to IPIC */
 		out_be32(&mdma->regs->dmaihsa, 0);
 		out_be32(&mdma->regs->dmailsa, 0);
-	} else {
-		/* MPC8308 has 16 channels and lacks some registers */
-		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
-
-		/* enable snooping */
-		out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
-		/* Disable error interrupts */
-		out_be32(&mdma->regs->dmaeeil, 0);
-
-		/* Clear interrupts status */
-		out_be32(&mdma->regs->dmaintl, 0xFFFF);
-		out_be32(&mdma->regs->dmaerrl, 0xFFFF);
 	}
 
 	/* Register DMA engine */
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH] mmc:of_spi: Update the code of getting voltage-ranges
From: Haijun Zhang @ 2013-07-31  6:25 UTC (permalink / raw)
  To: linux-mmc, linuxppc-dev
  Cc: scottwood, cjb, AFLEMING, Haijun Zhang, cbouatmailru
In-Reply-To: <1375251927-3330-1-git-send-email-Haijun.Zhang@freescale.com>

Using function mmc_of_parse_voltage() to get voltage-ranges.

Signed-off-by: Haijun Zhang <haijun.zhang@freescale.com>
---
 drivers/mmc/host/of_mmc_spi.c | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index d720b5e..7d10991 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -92,6 +92,7 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
 	struct of_mmc_spi *oms;
 	const u32 *voltage_ranges;
 	int num_ranges;
+	u32 ocr_mask;
 	int i;
 	int ret = -EINVAL;
 
@@ -102,26 +103,11 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
 	if (!oms)
 		return NULL;
 
-	voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
-	num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
-	if (!voltage_ranges || !num_ranges) {
-		dev_err(dev, "OF: voltage-ranges unspecified\n");
+	ocr_mask = mmc_of_parse_voltage(np);
+	if (ocr_mask <= 0)
 		goto err_ocr;
-	}
-
-	for (i = 0; i < num_ranges; i++) {
-		const int j = i * 2;
-		u32 mask;
 
-		mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
-					       be32_to_cpu(voltage_ranges[j + 1]));
-		if (!mask) {
-			ret = -EINVAL;
-			dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
-			goto err_ocr;
-		}
-		oms->pdata.ocr_mask |= mask;
-	}
+	oms->pdata.ocr_mask |= ocr_mask;
 
 	for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
 		enum of_gpio_flags gpio_flags;
-- 
1.8.0

^ permalink raw reply related

* [PATCH 3/3 V2] mmc:esdhc: add support to get voltage from device-tree
From: Haijun Zhang @ 2013-07-31  6:25 UTC (permalink / raw)
  To: linux-mmc, linuxppc-dev
  Cc: scottwood, cjb, AFLEMING, Haijun Zhang, cbouatmailru
In-Reply-To: <1375251927-3330-1-git-send-email-Haijun.Zhang@freescale.com>

Add suppport to get voltage from device-tree node for esdhc host,
if voltage-ranges was specified in device-tree node we can get
ocr_mask instead of read from host capacity register. If not voltages
still can be get from host capacity register.

Signed-off-by: Haijun Zhang <haijun.zhang@freescale.com>
---
changes for v2:
	- Update the parameters of function

 drivers/mmc/host/sdhci-of-esdhc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 15039e2..8a7e2af 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
 
 	/* call to generic mmc_of_parse to support additional capabilities */
 	mmc_of_parse(host->mmc);
+	host->ocr_mask = mmc_of_parse_voltage(np);
 
 	ret = sdhci_add_host(host);
 	if (ret)
-- 
1.8.0

^ permalink raw reply related

* [PATCH 1/3 V2] mmc:core: parse voltage from device-tree
From: Haijun Zhang @ 2013-07-31  6:25 UTC (permalink / raw)
  To: linux-mmc, linuxppc-dev
  Cc: scottwood, cjb, AFLEMING, Haijun Zhang, cbouatmailru

Add function to support get voltage from device-tree.
If there are voltage-range specified in device-tree node, this function
will parse it and return the avail voltage mask.

Signed-off-by: Haijun Zhang <haijun.zhang@freescale.com>
---
changes for v2:
	- Update the parameters of function

 drivers/mmc/core/core.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/core.h |  1 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 49a5bca..ce9c957 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,6 +27,7 @@
 #include <linux/fault-inject.h>
 #include <linux/random.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -1196,6 +1197,51 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
 }
 EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
 
+#ifdef CONFIG_OF
+
+/*
+ * mmc_of_parse_voltage - return mask of supported voltages
+ * @np: The device node need to be parsed.
+ *
+ * 1. Return zero: voltage-ranges unspecified in device-tree.
+ * 2. Return negative errno: voltage-range is invalid.
+ * 3. Return ocr_mask: a mask of voltages that parse from device-tree
+ * node can be provided to MMC/SD/SDIO devices.
+ */
+
+u32 mmc_of_parse_voltage(struct device_node *np)
+{
+	const u32 *voltage_ranges;
+	int num_ranges, i;
+	u32 ocr_mask = 0;
+
+	voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+	num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+	if (!voltage_ranges || !num_ranges) {
+		pr_info("%s: voltage-ranges unspecified\n", np->full_name);
+		return 0;
+	}
+
+	for (i = 0; i < num_ranges; i++) {
+		const int j = i * 2;
+		u32 mask;
+
+		mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
+				be32_to_cpu(voltage_ranges[j + 1]));
+		if (!mask) {
+			pr_err("%s: voltage-range #%d is invalid\n",
+				np->full_name, i);
+			return -EINVAL;
+		}
+		ocr_mask |= mask;
+	}
+
+	return ocr_mask;
+}
+EXPORT_SYMBOL(mmc_of_parse_voltage);
+
+#endif /* CONFIG_OF */
+
 #ifdef CONFIG_REGULATOR
 
 /**
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 443243b..e3f8fe3 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -209,5 +209,6 @@ static inline void mmc_claim_host(struct mmc_host *host)
 }
 
 extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
+extern u32 mmc_of_parse_voltage(struct device_node *np);
 
 #endif /* LINUX_MMC_CORE_H */
-- 
1.8.0

^ permalink raw reply related

* [PATCH v2] selftests: Add support files for powerpc tests
From: Michael Ellerman @ 2013-07-31  6:52 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Jeremy Kerr, Andrew Morton, Michael Neuling, linux-kernel,
	Anton Blanchard
In-Reply-To: <1375246593-26116-2-git-send-email-michael@ellerman.id.au>

This commit adds support code used by upcoming powerpc tests.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
v2: Put back the SIGALRM handler to make the hang logic work.

 tools/testing/selftests/powerpc/harness.c | 99 +++++++++++++++++++++++++++++++
 tools/testing/selftests/powerpc/subunit.h | 47 +++++++++++++++
 tools/testing/selftests/powerpc/utils.h   | 34 +++++++++++
 3 files changed, 180 insertions(+)
 create mode 100644 tools/testing/selftests/powerpc/harness.c
 create mode 100644 tools/testing/selftests/powerpc/subunit.h
 create mode 100644 tools/testing/selftests/powerpc/utils.h

diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
new file mode 100644
index 0000000..03f169d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "subunit.h"
+#include "utils.h"
+
+#define TIMEOUT		120
+#define KILL_TIMEOUT	5
+
+
+int run_test(int (test_function)(void), char *name)
+{
+	bool terminated;
+	int rc, status;
+	pid_t pid;
+
+	/* Make sure output is flushed before forking */
+	fflush(stdout);
+
+	pid = fork();
+	if (pid == 0) {
+		exit(test_function());
+	} else if (pid == -1) {
+		perror("fork");
+		return 1;
+	}
+
+	/* Wake us up in timeout seconds */
+	alarm(TIMEOUT);
+	terminated = false;
+
+wait:
+	rc = waitpid(pid, &status, 0);
+	if (rc == -1) {
+		if (errno != EINTR) {
+			printf("unknown error from waitpid\n");
+			return 1;
+		}
+
+		if (terminated) {
+			printf("!! force killing %s\n", name);
+			kill(pid, SIGKILL);
+			return 1;
+		} else {
+			printf("!! killing %s\n", name);
+			kill(pid, SIGTERM);
+			terminated = true;
+			alarm(KILL_TIMEOUT);
+			goto wait;
+		}
+	}
+
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	else
+		status = 1; /* Signal or other */
+
+	return status;
+}
+
+static void alarm_handler(int signum)
+{
+	/* Jut wake us up from waitpid */
+}
+
+static struct sigaction alarm_action = {
+	.sa_handler = alarm_handler,
+};
+
+int test_harness(int (test_function)(void), char *name)
+{
+	int rc;
+
+	test_start(name);
+	test_set_git_version(GIT_VERSION);
+
+	if (sigaction(SIGALRM, &alarm_action, NULL)) {
+		perror("sigaction");
+		test_error(name);
+		return 1;
+	}
+
+	rc = run_test(test_function, name);
+
+	test_finish(name, rc);
+
+	return rc;
+}
diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h
new file mode 100644
index 0000000..98a2292
--- /dev/null
+++ b/tools/testing/selftests/powerpc/subunit.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_SUBUNIT_H
+#define _SELFTESTS_POWERPC_SUBUNIT_H
+
+static inline void test_start(char *name)
+{
+	printf("test: %s\n", name);
+}
+
+static inline void test_failure_detail(char *name, char *detail)
+{
+	printf("failure: %s [%s]\n", name, detail);
+}
+
+static inline void test_failure(char *name)
+{
+	printf("failure: %s\n", name);
+}
+
+static inline void test_error(char *name)
+{
+	printf("error: %s\n", name);
+}
+
+static inline void test_success(char *name)
+{
+	printf("success: %s\n", name);
+}
+
+static inline void test_finish(char *name, int status)
+{
+	if (status)
+		test_failure(name);
+	else
+		test_success(name);
+}
+
+static inline void test_set_git_version(char *value)
+{
+	printf("tags: git_version:%s\n", value);
+}
+
+#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
new file mode 100644
index 0000000..5851c4b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_UTILS_H
+#define _SELFTESTS_POWERPC_UTILS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Avoid headaches with PRI?64 - just use %ll? always */
+typedef unsigned long long u64;
+typedef   signed long long s64;
+
+/* Just for familiarity */
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+
+int test_harness(int (test_function)(void), char *name);
+
+
+/* Yes, this is evil */
+#define FAIL_IF(x)						\
+do {								\
+	if ((x)) {						\
+		fprintf(stderr,					\
+		"[FAIL] Test FAILED on line %d\n", __LINE__);	\
+		return 1;					\
+	}							\
+} while (0)
+
+#endif /* _SELFTESTS_POWERPC_UTILS_H */
-- 
1.8.1.2

^ permalink raw reply related

* Re: [PATCH] powerpc: Remove SAVE_VSRU and REST_VSRU macros
From: Michael Neuling @ 2013-07-31  6:34 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: paulus, linuxppc-dev
In-Reply-To: <20130731161925.4fc8f5f2@kryten>

Anton Blanchard <anton@samba.org> wrote:

> 
> We always use VMX loads and stores to manage the high 32
> VSRs. Remove these unused macros.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>

Acked-by: Michael Neuling <mikey@neuling.org>


> ---
> 
> Index: b/arch/powerpc/include/asm/ppc_asm.h
> ===================================================================
> --- a/arch/powerpc/include/asm/ppc_asm.h
> +++ b/arch/powerpc/include/asm/ppc_asm.h
> @@ -219,19 +219,6 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLP
>  #define REST_8VSRS(n,b,base)	REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
>  #define REST_16VSRS(n,b,base)	REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,base)
>  #define REST_32VSRS(n,b,base)	REST_16VSRS(n,b,base); REST_16VSRS(n+16,b,base)
> -/* Save the upper 32 VSRs (32-63) in the thread VSX region (0-31) */
> -#define SAVE_VSRU(n,b,base)	li b,THREAD_VR0+(16*(n));  STXVD2X(n+32,R##base,R##b)
> -#define SAVE_2VSRSU(n,b,base)	SAVE_VSRU(n,b,base); SAVE_VSRU(n+1,b,base)
> -#define SAVE_4VSRSU(n,b,base)	SAVE_2VSRSU(n,b,base); SAVE_2VSRSU(n+2,b,base)
> -#define SAVE_8VSRSU(n,b,base)	SAVE_4VSRSU(n,b,base); SAVE_4VSRSU(n+4,b,base)
> -#define SAVE_16VSRSU(n,b,base)	SAVE_8VSRSU(n,b,base); SAVE_8VSRSU(n+8,b,base)
> -#define SAVE_32VSRSU(n,b,base)	SAVE_16VSRSU(n,b,base); SAVE_16VSRSU(n+16,b,base)
> -#define REST_VSRU(n,b,base)	li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,R##base,R##b)
> -#define REST_2VSRSU(n,b,base)	REST_VSRU(n,b,base); REST_VSRU(n+1,b,base)
> -#define REST_4VSRSU(n,b,base)	REST_2VSRSU(n,b,base); REST_2VSRSU(n+2,b,base)
> -#define REST_8VSRSU(n,b,base)	REST_4VSRSU(n,b,base); REST_4VSRSU(n+4,b,base)
> -#define REST_16VSRSU(n,b,base)	REST_8VSRSU(n,b,base); REST_8VSRSU(n+8,b,base)
> -#define REST_32VSRSU(n,b,base)	REST_16VSRSU(n,b,base); REST_16VSRSU(n+16,b,base)
>  
>  /*
>   * b = base register for addressing, o = base offset from register of 1st EVR
> 

^ permalink raw reply

* Re: [PATCH] powerpc: On POWERNV enable PPC_DENORMALISATION by default
From: Michael Neuling @ 2013-07-31  6:34 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: paulus, linuxppc-dev
In-Reply-To: <20130731163126.051976be@kryten>

Anton Blanchard <anton@samba.org> wrote:

> 
> We want PPC_DENORMALISATION enabled when POWERNV is enabled,
> so update the Kconfig.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>

Acked-by: Michael Neuling <mikey@neuling.org>

> ---
> 
> Index: b/arch/powerpc/Kconfig
> ===================================================================
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -566,7 +566,7 @@ config SCHED_SMT
>  config PPC_DENORMALISATION
>  	bool "PowerPC denormalisation exception handling"
>  	depends on PPC_BOOK3S_64
> -	default "n"
> +	default "y" if PPC_POWERNV
>  	---help---
>  	  Add support for handling denormalisation of single precision
>  	  values.  Useful for bare metal only.  If unsure say Y here.
> 

^ permalink raw reply

* [PATCH] powerpc: On POWERNV enable PPC_DENORMALISATION by default
From: Anton Blanchard @ 2013-07-31  6:31 UTC (permalink / raw)
  To: benh, paulus, mikey; +Cc: linuxppc-dev


We want PPC_DENORMALISATION enabled when POWERNV is enabled,
so update the Kconfig.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: b/arch/powerpc/Kconfig
===================================================================
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -566,7 +566,7 @@ config SCHED_SMT
 config PPC_DENORMALISATION
 	bool "PowerPC denormalisation exception handling"
 	depends on PPC_BOOK3S_64
-	default "n"
+	default "y" if PPC_POWERNV
 	---help---
 	  Add support for handling denormalisation of single precision
 	  values.  Useful for bare metal only.  If unsure say Y here.

^ permalink raw reply

* RE: [PATCH] cpuidle: add freescale e500 family porcessors idle support
From: Wang Dongsheng-B40534 @ 2013-07-31  6:30 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: Li Yang-R58472, linux-pm@vger.kernel.org,
	daniel.lezcano@linaro.org, rjw@sisk.pl, Zhao Chenhui-B35336,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1375213104.30721.79@snotra>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Wednesday, July 31, 2013 3:38 AM
> To: Wang Dongsheng-B40534
> Cc: rjw@sisk.pl; daniel.lezcano@linaro.org; benh@kernel.crashing.org; Li
> Yang-R58472; Zhao Chenhui-B35336; linux-pm@vger.kernel.org; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH] cpuidle: add freescale e500 family porcessors idle
> support
>=20
> On 07/30/2013 02:00:03 AM, Dongsheng Wang wrote:
> > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> >
> > Add cpuidle support for e500 family, using cpuidle framework to
> > manage various low power modes. The new implementation will remain
> > compatible with original idle method.
> >
> > Initially, this supports PW10, and subsequent patches will support
> > PW20/DOZE/NAP.
>=20
> Could you explain what the cpuidle framework does for us that the
> current idle code doesn't?
>=20

The current idle code, Only a state of low power can make the core idle.
The core can't get into more low power state.

> In particular, what scenario do you see where we would require a
> software
> governor to choose between idle states, and how much power is saved
> compared to a simpler approach?  There is timer that can be used to
> automatically enter PW20 after a certain amount of time in PW10.

Yes, the hardware can automatically enter PW20 state. But this is hardware
feature, we need to software to manage it. Only for PW20 state, we can drop
this cpuidle and using the hardware to control it. But if we need to suppor=
t
PH10/PH15/PH20/PH30, the current idle code cannot support them.=20

> How much better results do you get from a software governor?  Do we even
> have the right data to characterize each state so that a software governo=
r
> could make good decisions?  Is cpuidle capable of governing the interval
> of such a timer, rather than directly governing states?
>=20
>From now on we did not benchmark these data, because we only have PW10 stat=
e.

I can do support doze/nap for e6500. To get some data to show you.

> As for doze/nap, why would we want to use those on newer cores?  Do you
> have numbers for how much power each mode saves?
>=20
The PH state is plan to support, if the core can make into more low power s=
tate,
why not to do this.

PH10(doze)/PH15(nap)/PH20/PH30, These states can save more CPU power.

> Active governors may be useful on older cores that only have doze/nap,
> to
> select between them, but if that's the use case then why start with
> pw10?
Pw10 is supported on E500MC/E5500/E6500. And we plan to support PW20 for E6=
5OO core.
I will take doze/nap up a bit later.

> And I'd want to see numbers for how much power nap saves versus doze.
>=20
> > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
> > ---
> > This patch keep using cpuidle_register_device(), because we need to
> > support cpu
> > hotplug. I will fix "device" issue in this driver, after
> > Deepthi Dharwar <deepthi@linux.vnet.ibm.com> add a hotplug handler
> > into cpuidle
> > freamwork.
>=20
> Where's the diffstat?
>=20
See, http://patchwork.ozlabs.org/patch/260997/

> > @@ -0,0 +1,222 @@
> > +/*
> > + * Copyright 2013 Freescale Semiconductor, Inc.
> > + *
> > + * CPU Idle driver for Freescale PowerPC e500 family processors.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
> > + */
>=20
> Is this derived from some other file?  It looks like it...  Where's the
> attribution?
>=20
The copyright is from drivers/cpufreq/ppc-corenet-cpufreq.c

> > +#include <linux/cpu.h>
> > +#include <linux/cpuidle.h>
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/notifier.h>
> > +
> > +#include <asm/machdep.h>
> > +
> > +static struct cpuidle_driver e500_idle_driver =3D {
> > +	.name =3D "e500_idle",
> > +	.owner =3D THIS_MODULE,
> > +};
> > +
> > +static struct cpuidle_device __percpu *e500_cpuidle_devices;
> > +
> > +static void e500_cpuidle(void)
> > +{
> > +	/*
> > +	 * This would call on the cpuidle framework, and the back-end
> > +	 * driver to go to idle states.
> > +	 */
> > +	if (cpuidle_idle_call()) {
> > +		/*
> > +		 * On error, execute default handler
> > +		 * to go into low thread priority and possibly
> > +		 * low power mode.
> > +		 */
> > +		HMT_low();
> > +		HMT_very_low();
>=20
> This HMT stuff doesn't do anything on e500 derivatives AFAIK.
>=20
Yes, there should do nothing, let arch_cpu_idle to do the failed.

> > +static struct cpuidle_state fsl_pw_idle_states[] =3D {
> > +	{
> > +		.name =3D "pw10",
> > +		.desc =3D "pw10",
> > +		.flags =3D CPUIDLE_FLAG_TIME_VALID,
> > +		.exit_latency =3D 0,
> > +		.target_residency =3D 0,
> > +		.enter =3D &pw10_enter
>=20
> Where is pw10_enter defined?
>=20
In this patch..

> > +static int cpu_is_feature(unsigned long feature)
> > +{
> > +	return (cur_cpu_spec->cpu_features =3D=3D feature);
> > +}
> > +
> > +static int __init e500_idle_init(void)
> > +{
> > +	struct cpuidle_state *cpuidle_state_table =3D NULL;
> > +	struct cpuidle_driver *drv =3D &e500_idle_driver;
> > +	int err;
> > +	unsigned int max_idle_state =3D 0;
> > +
> > +	if (cpuidle_disable !=3D IDLE_NO_OVERRIDE)
> > +		return -ENODEV;
> > +
> > +	if (cpu_is_feature(CPU_FTRS_E500MC) ||
> > cpu_is_feature(CPU_FTRS_E5500) ||
> > +			cpu_is_feature(CPU_FTRS_E6500)) {
>=20
> There's no guarantee that a CPU with the same set of features is the
> exact same CPU.
>=20
> What specific feature are you looking for here?
>=20
Here is the type of the core. E500MC,E5500,E6500 do wait.

> > +		cpuidle_state_table =3D fsl_pw_idle_states;
> > +		max_idle_state =3D ARRAY_SIZE(fsl_pw_idle_states);
> > +	}
> > +
> > +	if (!cpuidle_state_table || !max_idle_state)
> > +		return -EPERM;
>=20
> ENODEV?
>=20
Looks better than EPERM.

-dongsheng

^ permalink raw reply

* Re: [PATCH 2/3] selftests: Add support files for powerpc tests
From: Michael Ellerman @ 2013-07-31  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Andrew Morton, Michael Neuling, Jeremy Kerr, Anton Blanchard,
	linux-kernel
In-Reply-To: <1375246593-26116-2-git-send-email-michael@ellerman.id.au>

On Wed, Jul 31, 2013 at 02:56:32PM +1000, Michael Ellerman wrote:
> This commit adds support code used by upcoming powerpc tests.

Fudge, I broke this one while "cleaning it up". Will send a v2.

cheers

^ permalink raw reply

* [PATCH] powerpc: Remove SAVE_VSRU and REST_VSRU macros
From: Anton Blanchard @ 2013-07-31  6:19 UTC (permalink / raw)
  To: benh, paulus, mikey; +Cc: linuxppc-dev


We always use VMX loads and stores to manage the high 32
VSRs. Remove these unused macros.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: b/arch/powerpc/include/asm/ppc_asm.h
===================================================================
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -219,19 +219,6 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLP
 #define REST_8VSRS(n,b,base)	REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
 #define REST_16VSRS(n,b,base)	REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,base)
 #define REST_32VSRS(n,b,base)	REST_16VSRS(n,b,base); REST_16VSRS(n+16,b,base)
-/* Save the upper 32 VSRs (32-63) in the thread VSX region (0-31) */
-#define SAVE_VSRU(n,b,base)	li b,THREAD_VR0+(16*(n));  STXVD2X(n+32,R##base,R##b)
-#define SAVE_2VSRSU(n,b,base)	SAVE_VSRU(n,b,base); SAVE_VSRU(n+1,b,base)
-#define SAVE_4VSRSU(n,b,base)	SAVE_2VSRSU(n,b,base); SAVE_2VSRSU(n+2,b,base)
-#define SAVE_8VSRSU(n,b,base)	SAVE_4VSRSU(n,b,base); SAVE_4VSRSU(n+4,b,base)
-#define SAVE_16VSRSU(n,b,base)	SAVE_8VSRSU(n,b,base); SAVE_8VSRSU(n+8,b,base)
-#define SAVE_32VSRSU(n,b,base)	SAVE_16VSRSU(n,b,base); SAVE_16VSRSU(n+16,b,base)
-#define REST_VSRU(n,b,base)	li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,R##base,R##b)
-#define REST_2VSRSU(n,b,base)	REST_VSRU(n,b,base); REST_VSRU(n+1,b,base)
-#define REST_4VSRSU(n,b,base)	REST_2VSRSU(n,b,base); REST_2VSRSU(n+2,b,base)
-#define REST_8VSRSU(n,b,base)	REST_4VSRSU(n,b,base); REST_4VSRSU(n+4,b,base)
-#define REST_16VSRSU(n,b,base)	REST_8VSRSU(n,b,base); REST_8VSRSU(n+8,b,base)
-#define REST_32VSRSU(n,b,base)	REST_16VSRSU(n,b,base); REST_16VSRSU(n+16,b,base)
 
 /*
  * b = base register for addressing, o = base offset from register of 1st EVR

^ permalink raw reply

* [PATCH] powerpc: Align p_toc
From: Anton Blanchard @ 2013-07-31  6:07 UTC (permalink / raw)
  To: benh, paulus; +Cc: linuxppc-dev


p_toc is an 8 byte relative offset to the TOC that we place in the
text section. This means it is only 4 byte aligned where it should
be 8 byte aligned. Add an explicit alignment.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: b/arch/powerpc/kernel/head_64.S
===================================================================
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -703,6 +703,7 @@ _GLOBAL(relative_toc)
 	mtlr	r0
 	blr
 
+.balign 8
 p_toc:	.llong	__toc_start + 0x8000 - 0b
 
 /*

^ permalink raw reply

* [PATCH] powerpc: Wrap MSR macros with parentheses
From: Anton Blanchard @ 2013-07-31  6:05 UTC (permalink / raw)
  To: benh, paulus; +Cc: linuxppc-dev


Not having parentheses around a macro is asking for trouble.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: b/arch/powerpc/include/asm/reg.h
===================================================================
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -115,10 +115,10 @@
 #define MSR_64BIT	MSR_SF
 
 /* Server variant */
-#define MSR_		MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV
-#define MSR_KERNEL	MSR_ | MSR_64BIT
-#define MSR_USER32	MSR_ | MSR_PR | MSR_EE
-#define MSR_USER64	MSR_USER32 | MSR_64BIT
+#define MSR_		(MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV)
+#define MSR_KERNEL	(MSR_ | MSR_64BIT)
+#define MSR_USER32	(MSR_ | MSR_PR | MSR_EE)
+#define MSR_USER64	(MSR_USER32 | MSR_64BIT)
 #elif defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_8xx)
 /* Default MSR for kernel mode. */
 #define MSR_KERNEL	(MSR_ME|MSR_RI|MSR_IR|MSR_DR)

^ permalink raw reply

* RE: [PATCH V2 4/6] cpuidle/pseries: Move the pseries_idle backend driver to sysdev.
From: Wang Dongsheng-B40534 @ 2013-07-31  5:46 UTC (permalink / raw)
  To: Preeti U Murthy
  Cc: Deepthi Dharwar, Li Yang-R58472, linux-pm@vger.kernel.org,
	daniel.lezcano@linaro.org, rjw@sisk.pl,
	linux-kernel@vger.kernel.org, Zhao Chenhui-B35336,
	srivatsa.bhat@linux.vnet.ibm.com, Wood Scott-B07421,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <51F88BA7.7090404@linux.vnet.ibm.com>

SGkgUHJlZXRpLA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IFByZWV0
aSBVIE11cnRoeSBbbWFpbHRvOnByZWV0aUBsaW51eC52bmV0LmlibS5jb21dDQo+IFNlbnQ6IFdl
ZG5lc2RheSwgSnVseSAzMSwgMjAxMyAxMjowMCBQTQ0KPiBUbzogV2FuZyBEb25nc2hlbmctQjQw
NTM0DQo+IENjOiBEZWVwdGhpIERoYXJ3YXI7IGJlbmhAa2VybmVsLmNyYXNoaW5nLm9yZzsgZGFu
aWVsLmxlemNhbm9AbGluYXJvLm9yZzsNCj4gbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsg
bWljaGFlbEBlbGxlcm1hbi5pZC5hdTsNCj4gc3JpdmF0c2EuYmhhdEBsaW51eC52bmV0LmlibS5j
b207IHN2YWlkeUBsaW51eC52bmV0LmlibS5jb207IGxpbnV4cHBjLQ0KPiBkZXZAbGlzdHMub3ps
YWJzLm9yZzsgcmp3QHNpc2sucGw7IGxpbnV4LXBtQHZnZXIua2VybmVsLm9yZw0KPiBTdWJqZWN0
OiBSZTogW1BBVENIIFYyIDQvNl0gY3B1aWRsZS9wc2VyaWVzOiBNb3ZlIHRoZSBwc2VyaWVzX2lk
bGUNCj4gYmFja2VuZCBkcml2ZXIgdG8gc3lzZGV2Lg0KPiANCj4gSGkgRG9uZ3NoZW5nLA0KPiAN
Cj4gT24gMDcvMzEvMjAxMyAwODo1MiBBTSwgV2FuZyBEb25nc2hlbmctQjQwNTM0IHdyb3RlOg0K
PiA+DQo+ID4NCj4gPj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPj4gRnJvbTogRGVl
cHRoaSBEaGFyd2FyIFttYWlsdG86ZGVlcHRoaUBsaW51eC52bmV0LmlibS5jb21dDQo+ID4+IFNl
bnQ6IFdlZG5lc2RheSwgSnVseSAzMSwgMjAxMyAxMDo1OSBBTQ0KPiA+PiBUbzogYmVuaEBrZXJu
ZWwuY3Jhc2hpbmcub3JnOyBkYW5pZWwubGV6Y2Fub0BsaW5hcm8ub3JnOyBsaW51eC0NCj4gPj4g
a2VybmVsQHZnZXIua2VybmVsLm9yZzsgbWljaGFlbEBlbGxlcm1hbi5pZC5hdTsNCj4gPj4gc3Jp
dmF0c2EuYmhhdEBsaW51eC52bmV0LmlibS5jb207IHByZWV0aUBsaW51eC52bmV0LmlibS5jb207
DQo+ID4+IHN2YWlkeUBsaW51eC52bmV0LmlibS5jb207IGxpbnV4cHBjLWRldkBsaXN0cy5vemxh
YnMub3JnDQo+ID4+IENjOiByandAc2lzay5wbDsgV2FuZyBEb25nc2hlbmctQjQwNTM0OyBsaW51
eC1wbUB2Z2VyLmtlcm5lbC5vcmcNCj4gPj4gU3ViamVjdDogW1BBVENIIFYyIDQvNl0gY3B1aWRs
ZS9wc2VyaWVzOiBNb3ZlIHRoZSBwc2VyaWVzX2lkbGUNCj4gPj4gYmFja2VuZCBkcml2ZXIgdG8g
c3lzZGV2Lg0KPiA+Pg0KPiA+PiBNb3ZlIHBzZXJpZXNfaWRsZSBiYWNrZW5kIGRyaXZlciBjb2Rl
IHRvIGFyY2gvcG93ZXJwYy9zeXNkZXYgc28gdGhhdA0KPiA+PiB0aGUgY29kZSBjYW4gYmUgdXNl
ZCBmb3IgYSBjb21tb24gZHJpdmVyIGZvciBwb3dlcm52IGFuZCBwc2VyaWVzLg0KPiA+PiBUaGlz
IHJlbW92ZXMgYSBsb3Qgb2YgY29kZSBkdXBsaWNhY3kuDQo+ID4+DQo+ID4gV2h5IG5vdCBkcml2
ZXJzL2NwdWlkbGUvPw0KPiA+DQo+ID4gSSB0aGluayBpdCBzaG91bGQgYmUgbW92ZSB0byBkcml2
ZXJzL2NwdWlkbGUuDQo+IA0KPiBQbGVhc2UgdGFrZSBhIGxvb2sgYXQgd2hhdCB0aGUgY3B1aWRs
ZSB1bmRlciBkcml2ZXJzIGhhcyB0byBwcm92aWRlLg0KPiBjcHVpZGxlIGhhcyB0d28gcGFydHMg
dG8gaXQuIFRoZSBmcm9udCBlbmQgYW5kIHRoZSBiYWNrIGVuZC4gVGhlIGZyb250DQo+IGVuZCBj
b25zdGl0dXRlcyB0aGUgY3B1aWRsZSBnb3Zlcm5vcnMsIHJlZ2lzdGVyaW5nIG9mIGFyY2ggc3Bl
Y2lmaWMNCj4gY3B1aWRsZSBkcml2ZXJzLCBkaXNhYmxpbmcgYW5kIGVuYWJsaW5nIG9mIGNwdWlk
bGUgZmVhdHVyZS4gSXQgaXMgdGhpcw0KPiBmcm9udCBlbmQgY29kZSB3aGljaCBpcyBwcmVzZW50
IHVuZGVyIGRyaXZlcnMvY3B1aWRsZS4NCj4gDQo+IFRoZSBhcmNoIHNwZWNpZmljIGNwdWlkbGUg
ZHJpdmVycyB3aGljaCBkZWNpZGUgd2hhdCBuZWVkcyB0byBiZSBkb25lIHRvDQo+IGVudGVyIGEg
c3BlY2lmaWMgaWRsZSBzdGF0ZSBjaG9zZW4gYnkgdGhlIGNwdWlkbGUgZ292ZXJub3IgaXMgd2hh
dA0KPiBjb25zdGl0dXRlcyB0aGUgYmFjayBlbmQgb2YgY3B1aWRsZS4gVGhpcyB3aWxsIG5vdCBi
ZSBpbiBkcml2ZXJzL2NwdWlkbGUNCj4gYnV0IGluIGFuIGFyY2gvIHNwZWNpZmljIGNvZGUuDQo+
IA0KPiBUaGUgY3B1aWRsZSB1bmRlciBkcml2ZXJzL2NwdWlkbGUgZHJpdmVzIHRoZSBpZGxlIHBv
d2VyIG1hbmFnZW1lbnQsIGJ1dA0KPiB0aGUgbG93IGxldmVsIGhhbmRsaW5nIG9mIHRoZSBlbnRy
eSBpbnRvIGlkbGUgc3RhdGVzIHNob3VsZCBiZSB0YWtlbiBjYXJlDQo+IG9mIGJ5IHRoZSBhcmNo
aXRlY3R1cmUuDQo+IA0KPiBZb3VyIHJlY2VudCBwYXRjaCA6DQo+IGNwdWlkbGU6IGFkZCBmcmVl
c2NhbGUgZTUwMCBmYW1pbHkgcG9yY2Vzc29ycyBpZGxlIHN1cHBvcnQgSU1PIHNob3VsZA0KPiBo
b29rIG9udG8gdGhlIGJhY2tlbmQgY3B1aWRsZSBkcml2ZXIgdGhhdCB0aGlzIHBhdGNoc2V0IHBy
b3ZpZGVzLg0KPiANClNvcnJ5LCBJIGRvbid0IHRoaW5rIHNvLCBjcHVpZGxlIGZyYW1ld29yayBo
YXMgYmVlbiBhbHJlYWR5IHZlcnkgY29tbW9uLg0KSGVyZSB3ZSBqdXN0IG5lZWQgdG8gZG8gc3Rh
dGUgZGVmaW5pdGlvbiBhbmQgaGFuZGxpbmcuIEkgd29uZGVyIHdoZXRoZXINCndlIG5lZWQgdGhp
cyBsYXllci4NCg0KSWYgeW91ciBoYW5kbGUgaXMgcGxhdGZvcm0gZGVwZW5kZW50LCBpdCBzaG91
bGQgYmUgaW4gYXJjaC9wbGF0Zm9ybS4NCg0KSWYgaXQgaXMgb25seSBmb3Igc29tZSBwbGF0Zm9y
bXMgYW5kIHRoZSBvcGVyYXRpb24gb2YgdGhlc2UgcGxhdGZvcm1zIGNhbiBiZQ0KbXVsdGlwbGV4
ZWQsIFdoeSBjYW5ub3QgYXMgYSBkcml2ZXIgdG8gcHV0IGludG8gZHJpdmVyL2NwdWlkbGU/DQoN
CklmIGl0IGEgZ2VuZXJhbCBkcml2ZXIsIEkgdGhpbmsgd2UgY2FuIHB1dCBzb21lIGNvbW1vbiBv
cGVyYXRpbmcgdG8gZHJpdmVyL2NwdWlkbGUNCmFuZCBtYWtlIHRoZSBwbGF0Zm9ybSBzcGVjaWZp
YyBjb2RlIHRvIGFyY2gvcG93ZXJwYy9wbGF0Zm9ybS4NCg0KVGhpcyBwYXRjaCBpbmNsdWRlIGZy
b250IGVuZCBhbmQgYmFjayBlbmQsIG5vdCBqdXN0IGJhY2sgZW5kLg0KDQpUaGlzIHBhdGNoIGlu
Y2x1ZGUgdG9vIG1hbnkgc3RhdGUgb2YgZGlmZmVyZW50IHBsYXRmb3JtcyBhbmQgaGFuZGxlIGZ1
bmN0aW9uLiBUaGlzIHN0YXRlDQphbmQgaGFuZGxlIHRoYXQgc2hvdWxkIGJlbG9uZyB0byBpdHNl
bGYgcGxhdGZvcm1zLiBOb3QgYSBnZW5lcmFsIHdheS4gSWYgRGVlcHRoaSB3aWxsIGRvDQphIGdl
bmVyYWwgcG93ZXJwYyBjcHVpZGxlLCBJIHRoaW5rLCBpdCdzIGNhbm5vdCBqdXN0IHVzaW5nIHRo
ZSBtYWNybyB0byBkaXN0aW5ndWlzaA0KcGxhdGZvcm0uIHRoZSBmcm9udCBlbmQgY29kZSBtYXli
ZSBtb3ZlIHRvIGRyaXZlci9jcHVpZGxlKGRydmllciByZWdpc3Rlcikgc2hvdWxkIGJlIGJldHRl
ciwNCm1ha2UgdGhlIExvdyBQb3dlciBTdGF0ZSBhbmQgd2hhdCBzaG91bGQgYmUgaGFuZGxlIHRv
IGFyY2gvcG93ZXJwYy9wbGF0Zm9ybS8qKiwgYmVjYXVzZSBkaWZmZXJlbnQNCnBsYXRmb3JtcyBo
YXZlIGRpZmZlcmVudCBzdGF0ZSBvZiBsb3cgcG93ZXIgY29uc3VtcHRpb24sIGFuZCB0aGUgcHJv
Y2Vzc2luZyBtZXRob2QuDQpUaGUgZnJvbnQgZW5kIGNhbiBwcm92aWRlIHNvbWUgZ2VuZXJhbCBt
ZXRob2RzIHRvIHJlZ2lzdGVyIGludG8gZ2VuZXJhbCBwb3dlcnBjIGNwdWlkbGUgZHJpdmVyLg0K
DQotZG9uZ3NoZW5nDQoNCg==

^ permalink raw reply

* RE: [PATCH 4/4] kvm: powerpc: set cache coherency only for RAM pages
From: Bhushan Bharat-R65777 @ 2013-07-31  5:23 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: linuxppc-dev@lists.ozlabs.org, Alexander Graf,
	kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
In-Reply-To: <1375210166.30721.77@snotra>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Wednesday, July 31, 2013 12:19 AM
> To: Bhushan Bharat-R65777
> Cc: Benjamin Herrenschmidt; Alexander Graf; kvm-ppc@vger.kernel.org;
> kvm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott-B07421
> Subject: Re: [PATCH 4/4] kvm: powerpc: set cache coherency only for RAM p=
ages
>=20
> On 07/30/2013 11:22:54 AM, Bhushan Bharat-R65777 wrote:
> > diff --git a/arch/powerpc/kvm/e500_mmu_host.c
> > b/arch/powerpc/kvm/e500_mmu_host.c
> > index 5cbdc8f..a48c13f 100644
> > --- a/arch/powerpc/kvm/e500_mmu_host.c
> > +++ b/arch/powerpc/kvm/e500_mmu_host.c
> > @@ -40,6 +40,84 @@
> >
> >  static struct kvmppc_e500_tlb_params host_tlb_params[E500_TLB_NUM];
> >
> > +/*
> > + * find_linux_pte returns the address of a linux pte for a given
> > + * effective address and directory.  If not found, it returns zero.
> > + */
> > +static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) {
> > +        pgd_t *pg;
> > +        pud_t *pu;
> > +        pmd_t *pm;
> > +        pte_t *pt =3D NULL;
> > +
> > +        pg =3D pgdir + pgd_index(ea);
> > +        if (!pgd_none(*pg)) {
> > +                pu =3D pud_offset(pg, ea);
> > +                if (!pud_none(*pu)) {
> > +                        pm =3D pmd_offset(pu, ea);
> > +                        if (pmd_present(*pm))
> > +                                pt =3D pte_offset_kernel(pm, ea);
> > +                }
> > +        }
> > +        return pt;
> > +}
>=20
> How is this specific to KVM or e500?
>=20
> > +#ifdef CONFIG_HUGETLB_PAGE
> > +pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
> > +                                 unsigned *shift); #else static
> > +inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir,
> > unsigned long ea,
> > +                                               unsigned *shift) {
> > +        if (shift)
> > +                *shift =3D 0;
> > +        return find_linux_pte(pgdir, ea); } #endif /*
> > +!CONFIG_HUGETLB_PAGE */
>=20
> This is already declared in asm/pgtable.h.  If we need a non-hugepage
> alternative, that should also go in asm/pgtable.h.
>=20
> > +/*
> > + * Lock and read a linux PTE.  If it's present and writable,
> > atomically
> > + * set dirty and referenced bits and return the PTE, otherwise
> > return 0.
> > + */
> > +static inline pte_t kvmppc_read_update_linux_pte(pte_t *p, int
> > writing)
> > +{
> > +       pte_t pte =3D pte_val(*p);
> > +
> > +       if (pte_present(pte)) {
> > +               pte =3D pte_mkyoung(pte);
> > +               if (writing && pte_write(pte))
> > +                       pte =3D pte_mkdirty(pte);
> > +       }
> > +
> > +       *p =3D pte;
> > +
> > +       return pte;
> > +}
> > +
> > +static pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
> > +                             int writing, unsigned long *pte_sizep) {
> > +       pte_t *ptep;
> > +       unsigned long ps =3D *pte_sizep;
> > +       unsigned int shift;
> > +
> > +       ptep =3D find_linux_pte_or_hugepte(pgdir, hva, &shift);
> > +       if (!ptep)
> > +               return __pte(0);
> > +       if (shift)
> > +               *pte_sizep =3D 1ul << shift;
> > +       else
> > +               *pte_sizep =3D PAGE_SIZE;
> > +
> > +       if (ps > *pte_sizep)
> > +               return __pte(0);
> > +       if (!pte_present(*ptep))
> > +               return __pte(0);
> > +
> > +       return kvmppc_read_update_linux_pte(ptep, writing); }
> > +
>=20
> None of this belongs in this file either.
>=20
> > @@ -326,8 +405,8 @@ static void kvmppc_e500_setup_stlbe(
> >
> >         /* Force IPROT=3D0 for all guest mappings. */
> >         stlbe->mas1 =3D MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) |
> > MAS1_VALID;
> > -       stlbe->mas2 =3D (gvaddr & MAS2_EPN) |
> > -                     e500_shadow_mas2_attrib(gtlbe->mas2, pfn);
> > +       stlbe->mas2 =3D (gvaddr & MAS2_EPN) | (ref->flags &
> > E500_TLB_WIMGE_MASK);
> > +//                   e500_shadow_mas2_attrib(gtlbe->mas2, pfn);
>=20
> MAS2_E and MAS2_G should be safe to come from the guest.

This is handled when setting WIMGE in ref->flags.

>=20
> How does this work for TLB1?  One ref corresponds to one guest entry, whi=
ch may
> correspond to multiple host entries, potentially each with different WIM
> settings.

Yes, one ref corresponds to one guest entry. To understand how this will wo=
rk when a one guest tlb1 entry may maps to many host tlb0/1 entry;=20
on guest tlbwe, KVM setup one guest tlb entry and then pre-map one host tlb=
 entry (out of many) and ref (ref->pfn etc) points to this pre-map entry fo=
r that guest entry.
Now a guest TLB miss happens which falls on same guest tlb entry and but de=
mands another host tlb entry. In that flow we change/overwrite ref (ref->pf=
n etc) to point to new host mapping for same guest mapping.

>=20
> >         stlbe->mas7_3 =3D ((u64)pfn << PAGE_SHIFT) |
> >                         e500_shadow_mas3_attrib(gtlbe->mas7_3, pr);
> >
> > @@ -346,6 +425,8 @@ static inline int kvmppc_e500_shadow_map(struct
> > kvmppc_vcpu_e500 *vcpu_e500,
> >         unsigned long hva;
> >         int pfnmap =3D 0;
> >         int tsize =3D BOOK3E_PAGESZ_4K;
> > +       pte_t pte;
> > +       int wimg =3D 0;
> >
> >         /*
> >          * Translate guest physical to true physical, acquiring @@
> > -451,6 +532,8 @@ static inline int kvmppc_e500_shadow_map(struct
> > kvmppc_vcpu_e500 *vcpu_e500,
> >
> >         if (likely(!pfnmap)) {
> >                 unsigned long tsize_pages =3D 1 << (tsize + 10 -
> > PAGE_SHIFT);
> > +               pgd_t *pgdir;
> > +
> >                 pfn =3D gfn_to_pfn_memslot(slot, gfn);
> >                 if (is_error_noslot_pfn(pfn)) {
> >                         printk(KERN_ERR "Couldn't get real page for
> > gfn %lx!\n", @@ -461,9 +544,15 @@ static inline int
> > kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
> >                 /* Align guest and physical address to page map
> > boundaries */
> >                 pfn &=3D ~(tsize_pages - 1);
> >                 gvaddr &=3D ~((tsize_pages << PAGE_SHIFT) - 1);
> > +               pgdir =3D vcpu_e500->vcpu.arch.pgdir;
> > +               pte =3D lookup_linux_pte(pgdir, hva, 1, &tsize_pages);
> > +               if (pte_present(pte))
> > +                       wimg =3D (pte >> PTE_WIMGE_SHIFT) &
> > MAS2_WIMGE_MASK;
> > +               else
> > +                       wimg =3D MAS2_I | MAS2_G;
>=20
> If the PTE is not present, then we can't map it, right?

Right, we should return error :)

-Bharat

>  So why I+G?
>=20
> -Scott

^ permalink raw reply

* [PATCH] powerpc: handle unaligned ldbrx/stdbrx
From: Anton Blanchard @ 2013-07-31  5:05 UTC (permalink / raw)
  To: benh, paulus, mikey; +Cc: linuxppc-dev


Normally when we haven't implemented an alignment handler for
a load or store instruction the process will be terminated.

The alignment handler uses the DSISR (or a pseudo one) to locate
the right handler. Unfortunately ldbrx and stdbrx overlap lfs and
stfs so we incorrectly think ldbrx is an lfs and stdbrx is an
stfs.

This bug is particularly nasty - instead of terminating the
process we apply an incorrect fixup and continue on.

With more and more overlapping instructions we should stop
creating a pseudo DSISR and index using the instruction directly,
but for now add a special case to catch ldbrx/stdbrx.

Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org>
---

Index: b/arch/powerpc/kernel/align.c
===================================================================
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -764,6 +764,16 @@ int fix_alignment(struct pt_regs *regs)
 	nb = aligninfo[instr].len;
 	flags = aligninfo[instr].flags;
 
+	/* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */
+	if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) {
+		nb = 8;
+		flags = LD+SW;
+	} else if (IS_XFORM(instruction) &&
+		   ((instruction >> 1) & 0x3ff) == 660) {
+		nb = 8;
+		flags = ST+SW;
+	}
+
 	/* Byteswap little endian loads and stores */
 	swiz = 0;
 	if (regs->msr & MSR_LE) {

^ permalink raw reply

* [PATCH 3/3] selftests: Add test of PMU instruction counting on powerpc
From: Michael Ellerman @ 2013-07-31  4:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Jeremy Kerr, Andrew Morton, Michael Neuling, linux-kernel,
	Anton Blanchard
In-Reply-To: <1375246593-26116-1-git-send-email-michael@ellerman.id.au>

This commit adds a test of instruction counting using the PMU on powerpc.

Although the bulk of the code is architecture agnostic, the code needs to
run a precisely sized loop which is implemented in assembler.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 tools/testing/selftests/powerpc/Makefile           |   2 +-
 tools/testing/selftests/powerpc/pmu/Makefile       |  23 ++++
 .../selftests/powerpc/pmu/count_instructions.c     | 135 +++++++++++++++++++++
 tools/testing/selftests/powerpc/pmu/event.c        | 105 ++++++++++++++++
 tools/testing/selftests/powerpc/pmu/event.h        |  39 ++++++
 tools/testing/selftests/powerpc/pmu/loop.S         |  46 +++++++
 6 files changed, 349 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/pmu/Makefile
 create mode 100644 tools/testing/selftests/powerpc/pmu/count_instructions.c
 create mode 100644 tools/testing/selftests/powerpc/pmu/event.c
 create mode 100644 tools/testing/selftests/powerpc/pmu/event.h
 create mode 100644 tools/testing/selftests/powerpc/pmu/loop.S

diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index bade865..7cb4744 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
 
 export CC CFLAGS
 
-TARGETS =
+TARGETS = pmu
 
 endif
 
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
new file mode 100644
index 0000000..7216f00
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -0,0 +1,23 @@
+noarg:
+	$(MAKE) -C ../
+
+PROGS := count_instructions
+EXTRA_SOURCES := ../harness.c event.c
+
+all: $(PROGS)
+
+$(PROGS): $(EXTRA_SOURCES)
+
+# loop.S can only be built 64-bit
+count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
+	$(CC) $(CFLAGS) -m64 -o $@ $^
+
+run_tests: all
+	@-for PROG in $(PROGS); do \
+		./$$PROG; \
+	done;
+
+clean:
+	rm -f $(PROGS) loop.o
+
+.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/pmu/count_instructions.c b/tools/testing/selftests/powerpc/pmu/count_instructions.c
new file mode 100644
index 0000000..312b4f0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/count_instructions.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/prctl.h>
+
+#include "event.h"
+#include "utils.h"
+
+extern void thirty_two_instruction_loop(u64 loops);
+
+static void setup_event(struct event *e, u64 config, char *name)
+{
+	event_init_opts(e, config, PERF_TYPE_HARDWARE, name);
+
+	e->attr.disabled = 1;
+	e->attr.exclude_kernel = 1;
+	e->attr.exclude_hv = 1;
+	e->attr.exclude_idle = 1;
+}
+
+static int do_count_loop(struct event *events, u64 instructions,
+			 u64 overhead, bool report)
+{
+	s64 difference, expected;
+	double percentage;
+
+	prctl(PR_TASK_PERF_EVENTS_ENABLE);
+
+	/* Run for 1M instructions */
+	thirty_two_instruction_loop(instructions >> 5);
+
+	prctl(PR_TASK_PERF_EVENTS_DISABLE);
+
+	event_read(&events[0]);
+	event_read(&events[1]);
+
+	expected = instructions + overhead;
+	difference = events[0].result.value - expected;
+	percentage = (double)difference / events[0].result.value * 100;
+
+	if (report) {
+		event_report(&events[0]);
+		event_report(&events[1]);
+
+		printf("Looped for %llu instructions, overhead %llu\n", instructions, overhead);
+		printf("Expected %llu\n", expected);
+		printf("Actual   %llu\n", events[0].result.value);
+		printf("Delta    %lld, %f%%\n", difference, percentage);
+	}
+
+	event_reset(&events[0]);
+	event_reset(&events[1]);
+
+	if (difference < 0)
+		difference = -difference;
+
+	/* Tolerate a difference below 0.0001 % */
+	difference *= 10000 * 100;
+	if (difference / events[0].result.value)
+		return -1;
+
+	return 0;
+}
+
+/* Count how many instructions it takes to do a null loop */
+static u64 determine_overhead(struct event *events)
+{
+	u64 current, overhead;
+	int i;
+
+	do_count_loop(events, 0, 0, false);
+	overhead = events[0].result.value;
+
+	for (i = 0; i < 100; i++) {
+		do_count_loop(events, 0, 0, false);
+		current = events[0].result.value;
+		if (current < overhead) {
+			printf("Replacing overhead %llu with %llu\n", overhead, current);
+			overhead = current;
+		}
+	}
+
+	return overhead;
+}
+
+static int count_instructions(void)
+{
+	struct event events[2];
+	u64 overhead;
+
+	setup_event(&events[0], PERF_COUNT_HW_INSTRUCTIONS, "instructions");
+	setup_event(&events[1], PERF_COUNT_HW_CPU_CYCLES, "cycles");
+
+	if (event_open(&events[0])) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	if (event_open_with_group(&events[1], events[0].fd)) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	overhead = determine_overhead(events);
+	printf("Overhead of null loop: %llu instructions\n", overhead);
+
+	/* Run for 1M instructions */
+	FAIL_IF(do_count_loop(events, 0x100000, overhead, true));
+
+	/* Run for 10M instructions */
+	FAIL_IF(do_count_loop(events, 0xa00000, overhead, true));
+
+	/* Run for 100M instructions */
+	FAIL_IF(do_count_loop(events, 0x6400000, overhead, true));
+
+	/* Run for 1G instructions */
+	FAIL_IF(do_count_loop(events, 0x40000000, overhead, true));
+
+	event_close(&events[0]);
+	event_close(&events[1]);
+
+	return 0;
+}
+
+int main(void)
+{
+	return test_harness(count_instructions, "count_instructions");
+}
diff --git a/tools/testing/selftests/powerpc/pmu/event.c b/tools/testing/selftests/powerpc/pmu/event.c
new file mode 100644
index 0000000..2b2d11d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+
+#include "event.h"
+
+
+int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
+		int group_fd, unsigned long flags)
+{
+	return syscall(__NR_perf_event_open, attr, pid, cpu,
+			   group_fd, flags);
+}
+
+void event_init_opts(struct event *e, u64 config, int type, char *name)
+{
+	memset(e, 0, sizeof(*e));
+
+	e->name = name;
+
+	e->attr.type = type;
+	e->attr.config = config;
+	e->attr.size = sizeof(e->attr);
+	/* This has to match the structure layout in the header */
+	e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \
+				  PERF_FORMAT_TOTAL_TIME_RUNNING;
+}
+
+void event_init_named(struct event *e, u64 config, char *name)
+{
+	event_init_opts(e, config, PERF_TYPE_RAW, name);
+}
+
+#define PERF_CURRENT_PID	0
+#define PERF_NO_CPU		-1
+#define PERF_NO_GROUP		-1
+
+int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd)
+{
+	e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0);
+	if (e->fd == -1) {
+		perror("perf_event_open");
+		return -1;
+	}
+
+	return 0;
+}
+
+int event_open_with_group(struct event *e, int group_fd)
+{
+	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd);
+}
+
+int event_open(struct event *e)
+{
+	return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP);
+}
+
+void event_close(struct event *e)
+{
+	close(e->fd);
+}
+
+int event_reset(struct event *e)
+{
+	return ioctl(e->fd, PERF_EVENT_IOC_RESET);
+}
+
+int event_read(struct event *e)
+{
+	int rc;
+
+	rc = read(e->fd, &e->result, sizeof(e->result));
+	if (rc != sizeof(e->result)) {
+		fprintf(stderr, "read error on event %p!\n", e);
+		return -1;
+	}
+
+	return 0;
+}
+
+void event_report_justified(struct event *e, int name_width, int result_width)
+{
+	printf("%*s: result %*llu ", name_width, e->name, result_width,
+	       e->result.value);
+
+	if (e->result.running == e->result.enabled)
+		printf("running/enabled %llu\n", e->result.running);
+	else
+		printf("running %llu enabled %llu\n", e->result.running,
+			e->result.enabled);
+}
+
+void event_report(struct event *e)
+{
+	event_report_justified(e, 0, 0);
+}
diff --git a/tools/testing/selftests/powerpc/pmu/event.h b/tools/testing/selftests/powerpc/pmu/event.h
new file mode 100644
index 0000000..e699319
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_PMU_EVENT_H
+#define _SELFTESTS_POWERPC_PMU_EVENT_H
+
+#include <unistd.h>
+#include <linux/perf_event.h>
+
+#include "utils.h"
+
+
+struct event {
+	struct perf_event_attr attr;
+	char *name;
+	int fd;
+	/* This must match the read_format we use */
+	struct {
+		u64 value;
+		u64 running;
+		u64 enabled;
+	} result;
+};
+
+void event_init(struct event *e, u64 config);
+void event_init_named(struct event *e, u64 config, char *name);
+void event_init_opts(struct event *e, u64 config, int type, char *name);
+int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd);
+int event_open_with_group(struct event *e, int group_fd);
+int event_open(struct event *e);
+void event_close(struct event *e);
+int event_reset(struct event *e);
+int event_read(struct event *e);
+void event_report_justified(struct event *e, int name_width, int result_width);
+void event_report(struct event *e);
+
+#endif /* _SELFTESTS_POWERPC_PMU_EVENT_H */
diff --git a/tools/testing/selftests/powerpc/pmu/loop.S b/tools/testing/selftests/powerpc/pmu/loop.S
new file mode 100644
index 0000000..8820e3d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/loop.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+	.text
+
+	.global thirty_two_instruction_loop
+	.type .thirty_two_instruction_loop,@function
+	.section ".opd","aw",@progbits
+thirty_two_instruction_loop:
+	.quad .thirty_two_instruction_loop, .TOC.@tocbase, 0
+	.previous
+.thirty_two_instruction_loop:
+	cmpwi	%r3,0
+	beqlr
+	addi	%r4,%r3,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1
+	addi	%r4,%r4,1	# 28 addi's
+	subi	%r3,%r3,1
+	b	.thirty_two_instruction_loop
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 2/3] selftests: Add support files for powerpc tests
From: Michael Ellerman @ 2013-07-31  4:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Jeremy Kerr, Andrew Morton, Michael Neuling, linux-kernel,
	Anton Blanchard
In-Reply-To: <1375246593-26116-1-git-send-email-michael@ellerman.id.au>

This commit adds support code used by upcoming powerpc tests.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 tools/testing/selftests/powerpc/harness.c | 83 +++++++++++++++++++++++++++++++
 tools/testing/selftests/powerpc/subunit.h | 47 +++++++++++++++++
 tools/testing/selftests/powerpc/utils.h   | 34 +++++++++++++
 3 files changed, 164 insertions(+)
 create mode 100644 tools/testing/selftests/powerpc/harness.c
 create mode 100644 tools/testing/selftests/powerpc/subunit.h
 create mode 100644 tools/testing/selftests/powerpc/utils.h

diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
new file mode 100644
index 0000000..ad73a34
--- /dev/null
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "subunit.h"
+#include "utils.h"
+
+#define TIMEOUT		120
+#define KILL_TIMEOUT	5
+
+
+int run_test(int (test_function)(void), char *name)
+{
+	bool terminated;
+	int rc, status;
+	pid_t pid;
+
+	/* Make sure output is flushed before forking */
+	fflush(stdout);
+
+	pid = fork();
+	if (pid == 0) {
+		exit(test_function());
+	} else if (pid == -1) {
+		perror("fork");
+		return 1;
+	}
+
+	/* Wake us up in timeout seconds */
+	alarm(TIMEOUT);
+	terminated = false;
+
+wait:
+	rc = waitpid(pid, &status, 0);
+	if (rc == -1) {
+		if (errno != EINTR) {
+			printf("unknown error from waitpid\n");
+			return 1;
+		}
+
+		if (terminated) {
+			printf("!! force killing %s\n", name);
+			kill(pid, SIGKILL);
+			return 1;
+		} else {
+			printf("!! killing %s\n", name);
+			kill(pid, SIGTERM);
+			terminated = true;
+			alarm(KILL_TIMEOUT);
+			goto wait;
+		}
+	}
+
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	else
+		status = 1; /* Signal or other */
+
+	return status;
+}
+
+int test_harness(int (test_function)(void), char *name)
+{
+	int rc;
+
+	test_start(name);
+	test_set_git_version(GIT_VERSION);
+
+	rc = run_test(test_function, name);
+
+	test_finish(name, rc);
+
+	return rc;
+}
diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h
new file mode 100644
index 0000000..98a2292
--- /dev/null
+++ b/tools/testing/selftests/powerpc/subunit.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_SUBUNIT_H
+#define _SELFTESTS_POWERPC_SUBUNIT_H
+
+static inline void test_start(char *name)
+{
+	printf("test: %s\n", name);
+}
+
+static inline void test_failure_detail(char *name, char *detail)
+{
+	printf("failure: %s [%s]\n", name, detail);
+}
+
+static inline void test_failure(char *name)
+{
+	printf("failure: %s\n", name);
+}
+
+static inline void test_error(char *name)
+{
+	printf("error: %s\n", name);
+}
+
+static inline void test_success(char *name)
+{
+	printf("success: %s\n", name);
+}
+
+static inline void test_finish(char *name, int status)
+{
+	if (status)
+		test_failure(name);
+	else
+		test_success(name);
+}
+
+static inline void test_set_git_version(char *value)
+{
+	printf("tags: git_version:%s\n", value);
+}
+
+#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
new file mode 100644
index 0000000..5851c4b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corp.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _SELFTESTS_POWERPC_UTILS_H
+#define _SELFTESTS_POWERPC_UTILS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Avoid headaches with PRI?64 - just use %ll? always */
+typedef unsigned long long u64;
+typedef   signed long long s64;
+
+/* Just for familiarity */
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+
+int test_harness(int (test_function)(void), char *name);
+
+
+/* Yes, this is evil */
+#define FAIL_IF(x)						\
+do {								\
+	if ((x)) {						\
+		fprintf(stderr,					\
+		"[FAIL] Test FAILED on line %d\n", __LINE__);	\
+		return 1;					\
+	}							\
+} while (0)
+
+#endif /* _SELFTESTS_POWERPC_UTILS_H */
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 1/3] selftests: Add infrastructure for powerpc selftests
From: Michael Ellerman @ 2013-07-31  4:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Jeremy Kerr, Andrew Morton, Michael Neuling, linux-kernel,
	Anton Blanchard

This commit adds a powerpc subdirectory to tools/testing/selftests,
for tests that are powerpc specific.

On other architectures nothing is built. The makefile supports cross
compilation if the user sets ARCH and CROSS_COMPILE.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 tools/testing/selftests/Makefile         |  1 +
 tools/testing/selftests/powerpc/Makefile | 35 ++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 tools/testing/selftests/powerpc/Makefile

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4cb14ca..9f3eae2 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -8,6 +8,7 @@ TARGETS += net
 TARGETS += ptrace
 TARGETS += timers
 TARGETS += vm
+TARGETS += powerpc
 
 all:
 	for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
new file mode 100644
index 0000000..bade865
--- /dev/null
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -0,0 +1,35 @@
+# Makefile for powerpc selftests
+
+# ARCH can be overridden by the user for cross compiling
+ARCH ?= $(shell uname -m)
+ARCH := $(shell echo $(ARCH) | sed -e s/ppc.*/powerpc/)
+
+ifeq ($(ARCH),powerpc)
+
+GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
+
+CC := $(CROSS_COMPILE)$(CC)
+CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
+
+export CC CFLAGS
+
+TARGETS =
+
+endif
+
+all:
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET all; \
+	done;
+
+run_tests: all
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET run_tests; \
+	done;
+
+clean:
+	@for TARGET in $(TARGETS); do \
+		$(MAKE) -C $$TARGET clean; \
+	done;
+
+.PHONY: all run_tests clean
-- 
1.8.1.2

^ permalink raw reply related

* Re: [PATCH V2 4/6] cpuidle/pseries: Move the pseries_idle backend driver to sysdev.
From: Preeti U Murthy @ 2013-07-31  3:59 UTC (permalink / raw)
  To: Wang Dongsheng-B40534
  Cc: Deepthi Dharwar, linux-pm@vger.kernel.org,
	daniel.lezcano@linaro.org, rjw@sisk.pl,
	linux-kernel@vger.kernel.org, srivatsa.bhat@linux.vnet.ibm.com,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <ABB05CD9C9F68C46A5CEDC7F15439259FF2953@039-SN2MPN1-021.039d.mgd.msft.net>

Hi Dongsheng,

On 07/31/2013 08:52 AM, Wang Dongsheng-B40534 wrote:
> 
> 
>> -----Original Message-----
>> From: Deepthi Dharwar [mailto:deepthi@linux.vnet.ibm.com]
>> Sent: Wednesday, July 31, 2013 10:59 AM
>> To: benh@kernel.crashing.org; daniel.lezcano@linaro.org; linux-
>> kernel@vger.kernel.org; michael@ellerman.id.au;
>> srivatsa.bhat@linux.vnet.ibm.com; preeti@linux.vnet.ibm.com;
>> svaidy@linux.vnet.ibm.com; linuxppc-dev@lists.ozlabs.org
>> Cc: rjw@sisk.pl; Wang Dongsheng-B40534; linux-pm@vger.kernel.org
>> Subject: [PATCH V2 4/6] cpuidle/pseries: Move the pseries_idle backend
>> driver to sysdev.
>>
>> Move pseries_idle backend driver code to arch/powerpc/sysdev
>> so that the code can be used for a common driver for powernv
>> and pseries. This removes a lot of code duplicacy.
>>
> Why not drivers/cpuidle/?
> 
> I think it should be move to drivers/cpuidle.

Please take a look at what the cpuidle under drivers has to provide.
cpuidle has two parts to it. The front end and the back end. The front
end constitutes the cpuidle governors, registering of arch specific
cpuidle drivers, disabling and enabling of cpuidle feature. It is this
front end code which is present under drivers/cpuidle.

The arch specific cpuidle drivers which decide what needs to be done to
enter a specific idle state chosen by the cpuidle governor is what
constitutes the back end of cpuidle. This will not be in drivers/cpuidle
but in an arch/ specific code.

The cpuidle under drivers/cpuidle drives the idle power management, but
the low level handling of the entry into idle states should be taken
care of by the architecture.

Your recent patch :
cpuidle: add freescale e500 family porcessors idle support IMO should
hook onto the backend cpuidle driver that this patchset provides.

Regards
Preeti U Murthy

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox