LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6/10] arch/powerpc/platforms/pseries: Use kstrdup
From: Julia Lawall @ 2010-05-14 19:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
	linux-kernel, kernel-janitors

From: Julia Lawall <julia@diku.dk>

Use kstrdup when the goal of an allocation is copy a string into the
allocated region.

The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)

// <smpl>
@@
expression from,to;
expression flag,E1,E2;
statement S;
@@

-  to = kmalloc(strlen(from) + 1,flag);
+  to = kstrdup(from, flag);
   ... when != \(from = E1 \| to = E1 \)
   if (to==NULL || ...) S
   ... when != \(from = E2 \| to = E2 \)
-  strcpy(to, from);
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>

---
 arch/powerpc/platforms/pseries/reconfig.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff -u -p a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -118,12 +118,10 @@ static int pSeries_reconfig_add_node(con
 	if (!np)
 		goto out_err;
 
-	np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+	np->full_name = kstrdup(path, GFP_KERNEL);
 	if (!np->full_name)
 		goto out_err;
 
-	strcpy(np->full_name, path);
-
 	np->properties = proplist;
 	of_node_set_flag(np, OF_DYNAMIC);
 	kref_init(&np->kref);

^ permalink raw reply

* [PATCH 10/10] arch/powerpc/platforms/iseries: Use kstrdup
From: Julia Lawall @ 2010-05-14 19:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Grant Likely,
	linuxppc-dev, linux-kernel, devicetree-discuss, kernel-janitors

From: Julia Lawall <julia@diku.dk>

Use kstrdup when the goal of an allocation is copy a string into the
allocated region.

The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)

// <smpl>
@@
expression from,to;
expression flag,E1,E2;
statement S;
@@

-  to = kmalloc(strlen(from) + 1,flag);
+  to = kstrdup(from, flag);
   ... when != \(from = E1 \| to = E1 \)
   if (to==NULL || ...) S
   ... when != \(from = E2 \| to = E2 \)
-  strcpy(to, from);
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>

---
 arch/powerpc/platforms/iseries/vio.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff -u -p a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -87,12 +87,11 @@ static struct device_node *new_node(cons
 
 	if (!np)
 		return NULL;
-	np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+	np->full_name = kstrdup(path, GFP_KERNEL);
 	if (!np->full_name) {
 		kfree(np);
 		return NULL;
 	}
-	strcpy(np->full_name, path);
 	of_node_set_flag(np, OF_DYNAMIC);
 	kref_init(&np->kref);
 	np->parent = of_node_get(parent);

^ permalink raw reply

* mpc870 support in the powerpc arch?
From: Shawn Jin @ 2010-05-14 21:41 UTC (permalink / raw)
  To: ppcdev

Hi,

Is mpc870 fully supported in the powerpc arch? I know it's an old
processor but 8xx is still one of platforms in the powerpc arch. If
it's not supported, how much effort will it be to resurrect mpc870 in
the new arch considering we have substantial 8xx support?

Thanks,
-Shawn.

^ permalink raw reply

* Re: [PATCH]460EX on-chip SATA driver <Kernel 2.6.33> < resubmission >
From: Jeff Garzik @ 2010-05-14 21:56 UTC (permalink / raw)
  To: Rupjyoti Sarmah
  Cc: Sergei Shtylyov, linuxppc-dev, linux-kernel, linux-ide, sr
In-Reply-To: <201005051757.o45HvPmY005954@amcc.com>

On 05/05/2010 01:57 PM, Rupjyoti Sarmah wrote:
> +static  void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
> +{
> +	out_le32(&hsdev->sata_dwc_regs->intpr,
> +		 in_le32(&hsdev->sata_dwc_regs->intpr));
> +}
> +
> +static  u32 qcmd_tag_to_mask(u8 tag)
> +{
> +	return 0x00000001<<  (tag&  0x1f);
> +}
> +
> +/* See ahci.c */
> +static void sata_dwc_error_intr(struct ata_port *ap,
> +				struct sata_dwc_device *hsdev, uint intpr)
> +{
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	struct ata_eh_info *ehi =&ap->link.eh_info;
> +	unsigned int err_mask = 0, action = 0;
> +	struct ata_queued_cmd *qc;
> +	u32 serror;
> +	u8 status, tag;
> +	u32 err_reg;
> +
> +	ata_ehi_clear_desc(ehi);
> +
> +	serror = core_scr_read(SCR_ERROR);
> +	status = ap->ops->sff_check_status(ap);
> +
> +	err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error.\
> +			low));
> +	tag = ap->link.active_tag;
> +
> +	dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x "
> +		"dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n",
> +		__func__, serror, intpr, status, host_pvt.dma_interrupt_count,
> +		hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg);
> +
> +	/* Clear error register and interrupt bit */
> +	clear_serror();
> +	clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);
> +
> +	/* This is the only error happening now.  TODO check for exact error */
> +	err_mask |= AC_ERR_HOST_BUS;
> +	action |= ATA_EH_RESET;

this is a rather poor error mapping.


> +/******************************************************************************
> + * Function : sata_dwc_isr
> + * arguments : irq, void *dev_instance, struct pt_regs *regs
> + * Return value : irqreturn_t - status of IRQ
> + * This Interrupt handler called via port ops registered function.
> + * .irq_handler = sata_dwc_isr
> + *****************************************************************************/
> +static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
> +{
> +	struct ata_host *host = (struct ata_host *)dev_instance;
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_HOST(host);
> +	struct ata_port *ap;
> +	struct ata_queued_cmd *qc;
> +	unsigned long flags;
> +	u8 status, tag;
> +	int handled, num_processed, port = 0;
> +	uint intpr, sactive, sactive2, tag_mask;
> +	struct sata_dwc_device_port *hsdevp;
> +	host_pvt.sata_dwc_sactive_issued = 0;
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +
> +	/* Read the interrupt register */
> +	intpr = in_le32(&hsdev->sata_dwc_regs->intpr);
> +
> +	ap = host->ports[port];
> +	hsdevp = HSDEVP_FROM_AP(ap);
> +
> +	dev_dbg(ap->dev, "%s intpr=0x%08x active_tag=%d\n", __func__, intpr,
> +		ap->link.active_tag);
> +
> +	/* Check for error interrupt */
> +	if (intpr&  SATA_DWC_INTPR_ERR) {
> +		sata_dwc_error_intr(ap, hsdev, intpr);
> +		handled = 1;
> +		goto DONE;
> +	}
> +
> +	/* Check for DMA SETUP FIS (FP DMA) interrupt */
> +	if (intpr&  SATA_DWC_INTPR_NEWFP) {
> +		clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP);
> +
> +		tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr));
> +		dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag);
> +		if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
> +			dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);
> +
> +		host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag);
> +
> +		qc = ata_qc_from_tag(ap, tag);
> +		/* Start FP DMA for NCQ command.  At this point the tag is the
> +		 * active tag.  It is the tag that matches the command about to
> +		 * be completed.
> +		 */
> +		qc->ap->link.active_tag = tag;
> +		sata_dwc_bmdma_start_by_tag(qc, tag);
> +
> +		handled = 1;
> +		goto DONE;
> +	}
> +
> +	sactive = core_scr_read(SCR_ACTIVE);
> +	tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
> +
> +	/* If no sactive issued and tag_mask is zero then this is not NCQ */
> +	if (host_pvt.sata_dwc_sactive_issued == 0&&  tag_mask == 0) {
> +		if (ap->link.active_tag == ATA_TAG_POISON)
> +			tag = 0;
> +		else
> +			tag = ap->link.active_tag;
> +		qc = ata_qc_from_tag(ap, tag);
> +
> +		/* DEV interrupt w/ no active qc? */
> +		if (unlikely(!qc || (qc->tf.flags&  ATA_TFLAG_POLLING))) {
> +			dev_err(ap->dev, "%s interrupt with no active qc "
> +				"qc=%p\n", __func__, qc);
> +			ap->ops->sff_check_status(ap);
> +			handled = 1;
> +			goto DONE;
> +		}
> +
> +		status = ap->ops->sff_check_status(ap);
> +
> +		qc->ap->link.active_tag = tag;
> +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT;
> +
> +		if (status&  ATA_ERR) {
> +			dev_dbg(ap->dev, "interrupt ATA_ERR (0x%x)\n", status);
> +			sata_dwc_qc_complete(ap, qc, 1);
> +			handled = 1;
> +			goto DONE;
> +		}
> +
> +		dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n",
> +			__func__, ata_get_cmd_descript(qc->tf.protocol));
> +DRVSTILLBUSY:
> +		if (ata_is_dma(qc->tf.protocol)) {
> +			/* Each DMA transaction produces 2 interrupts. The DMAC
> +			 * transfer complete interrupt and the SATA controller
> +			 * operation done interrupt. The command should be
> +			 * completed only after both interrupts are seen.
> +			 */
> +			host_pvt.dma_interrupt_count++;
> +			if (hsdevp->dma_pending[tag] == \
> +					SATA_DWC_DMA_PENDING_NONE) {
> +				dev_err(ap->dev, "%s: DMA not pending "
> +					"intpr=0x%08x status=0x%08x pending"
> +					"=%d\n", __func__, intpr, status,
> +					hsdevp->dma_pending[tag]);
> +			}
> +
> +			if ((host_pvt.dma_interrupt_count % 2) == 0)
> +				sata_dwc_dma_xfer_complete(ap, 1);
> +		} else if (ata_is_pio(qc->tf.protocol)) {
> +			ata_sff_hsm_move(ap, qc, status, 0);
> +			handled = 1;
> +			goto DONE;
> +		} else {
> +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1)))
> +				goto DRVSTILLBUSY;
> +		}
> +
> +		handled = 1;
> +		goto DONE;
> +	}
> +
> +	/*
> +	 * This is a NCQ command. At this point we need to figure out for which
> +	 * tags we have gotten a completion interrupt.  One interrupt may serve
> +	 * as completion for more than one operation when commands are queued
> +	 * (NCQ).  We need to process each completed command.
> +	 */
> +
> +	 /* process completed commands */
> +	sactive = core_scr_read(SCR_ACTIVE);
> +	tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
> +
> +	if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued)>  1 || \
> +							tag_mask>  1) {
> +		dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x  sactive_issued=0x%08x"
> +			"tag_mask=0x%08x\n", __func__, sactive,
> +			host_pvt.sata_dwc_sactive_issued, tag_mask);
> +	}
> +
> +	if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \
> +					(host_pvt.sata_dwc_sactive_issued)) {
> +		dev_warn(ap->dev, "Bad tag mask?  sactive=0x%08x "
> +			 "(host_pvt.sata_dwc_sactive_issued)=0x%08x  tag_mask"
> +			 "=0x%08x\n", sactive, host_pvt.sata_dwc_sactive_issued,
> +			  tag_mask);
> +	}
> +
> +	/* read just to clear ... not bad if currently still busy */
> +	status = ap->ops->sff_check_status(ap);
> +	dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
> +
> +	tag = 0;
> +	num_processed = 0;
> +	while (tag_mask) {
> +		num_processed++;
> +		while (!(tag_mask&  0x00000001)) {
> +			tag++;
> +			tag_mask<<= 1;
> +		}
> +		tag_mask&= (~0x00000001);
> +		qc = ata_qc_from_tag(ap, tag);
> +
> +		/* To be picked up by completion functions */
> +		qc->ap->link.active_tag = tag;
> +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT;
> +
> +		/* Let libata/scsi layers handle error */
> +		if (status&  ATA_ERR) {
> +			dev_dbg(ap->dev, "%s ATA_ERR (0x%x)\n", __func__,
> +				status);
> +			sata_dwc_qc_complete(ap, qc, 1);
> +			handled = 1;
> +			goto DONE;
> +		}
> +
> +		/* Process completed command */
> +		dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__,
> +			ata_get_cmd_descript(qc->tf.protocol));
> +		if (ata_is_dma(qc->tf.protocol)) {
> +			host_pvt.dma_interrupt_count++;
> +			if (hsdevp->dma_pending[tag] == \
> +					SATA_DWC_DMA_PENDING_NONE)
> +				dev_warn(ap->dev, "%s: DMA not pending?\n",
> +					__func__);
> +			if ((host_pvt.dma_interrupt_count % 2) == 0)
> +				sata_dwc_dma_xfer_complete(ap, 1);
> +		} else {
> +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1)))
> +				goto STILLBUSY;
> +		}
> +		continue;
> +
> +STILLBUSY:
> +		ap->stats.idle_irq++;
> +		dev_warn(ap->dev, "STILL BUSY IRQ ata%d: irq trap\n",
> +			ap->print_id);
> +	} /* while tag_mask */

why not use ata_qc_complete_multiple?


> +static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
> +{
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);
> +
> +	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) {
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +			 SATA_DWC_DMACR_RX_CLEAR(
> +				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
> +	} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) {
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +			 SATA_DWC_DMACR_TX_CLEAR(
> +				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
> +	} else {
> +		/* This should not happen, it indicates the driver is out of
> +		 * sync.  If it does happen, clear dmacr anyway.
> +		 */
> +		dev_err(host_pvt.dwc_dev, "%s DMA protocol RX and"
> +			"TX DMA not pending tag=0x%02x pending=%d"
> +			" dmacr: 0x%08x\n", __func__, tag,
> +			hsdevp->dma_pending[tag],
> +			in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +			SATA_DWC_DMACR_TXRXCH_CLEAR);
> +	}
> +}
> +
> +static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
> +{
> +	struct ata_queued_cmd *qc;
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
> +	u8 tag = 0;
> +
> +	tag = ap->link.active_tag;
> +	qc = ata_qc_from_tag(ap, tag);

Note that qc may equal NULL!


> +#ifdef DEBUG_NCQ
> +	if (tag>  0) {
> +		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "
> +			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command,
> +			 ata_get_cmd_descript(qc->dma_dir),
> +			 ata_get_cmd_descript(qc->tf.protocol),
> +			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +	}
> +#endif
> +
> +	if (ata_is_dma(qc->tf.protocol)) {
> +		if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) {
> +			dev_err(ap->dev, "%s DMA protocol RX and TX DMA not "
> +				"pending dmacr: 0x%08x\n", __func__,
> +				in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +		}
> +
> +		hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE;
> +		sata_dwc_qc_complete(ap, qc, check_status);
> +		ap->link.active_tag = ATA_TAG_POISON;
> +	} else {
> +		sata_dwc_qc_complete(ap, qc, check_status);
> +	}
> +}
> +
> +static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
> +				u32 check_status)
> +{
> +	u8 status = 0;
> +	int i = 0;
> +	u32 mask = 0x0;
> +	u8 tag = qc->tag;
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	u32 serror;
> +	host_pvt.sata_dwc_sactive_queued = 0;
> +	dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status);
> +
> +	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX)
> +		dev_err(ap->dev, "TX DMA PENDING\n");
> +	else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX)
> +		dev_err(ap->dev, "RX DMA PENDING\n");
> +
> +	if (check_status) {
> +		i = 0;
> +		do {
> +			/* check main status, clearing INTRQ */
> +			status = ap->ops->sff_check_status(ap);
> +			if (status&  ATA_BUSY) {
> +				dev_dbg(ap->dev, "STATUS BUSY (0x%02x) [%d]\n",
> +						status, i);
> +			}
> +			if (++i>  10)
> +				break;
> +		} while (status&  ATA_BUSY);
> +
> +		status = ap->ops->sff_check_status(ap);
> +		if (unlikely(status&  ATA_BUSY))
> +			dev_err(ap->dev, "QC complete cmd=0x%02x STATUS BUSY"
> +				" (0x%02x)[%d]\n", qc->tf.command, status, i);
> +		serror = core_scr_read(SCR_ERROR);
> +		if (serror&  SATA_DWC_SERROR_ERR_BITS)
> +			dev_err(ap->dev, "****** SERROR=0x%08x ******\n",
> +				serror);
> +	}
> +	dev_dbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u:"
> +		" protocol=%d\n", qc->tf.command, status, ap->print_id,
> +		 qc->tf.protocol);
> +
> +	/* clear active bit */
> +	mask = (~(qcmd_tag_to_mask(tag)));
> +	host_pvt.sata_dwc_sactive_queued = (host_pvt.sata_dwc_sactive_queued) \
> +						&  mask;
> +	host_pvt.sata_dwc_sactive_issued = (host_pvt.sata_dwc_sactive_issued) \
> +						&  mask;
> +
> +	/* Complete taskfile transaction (does not read SCR registers) */
> +	ata_qc_complete(qc);
> +
> +	return 0;

why is this loop in qc_complete?  That is highly unusual.


> +/******************************************************************************
> + * Function : sata_dwc_qc_prep
> + * arguments : ata_queued_cmd *qc
> + * Return value : None
> + * qc_prep for a particular queued command
> + *****************************************************************************/
> +#if 1
> +static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)
> +{
> +	if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO))
> +		return;
> +
> +#ifdef DEBUG_NCQ
> +	if (qc->tag>  0)
> +		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
> +			 __func__, tag, qc->ap->link.active_tag);
> +
> +	return ;
> +#endif
> +}
> +#endif
> +static void sata_dwc_error_handler(struct ata_port *ap)
> +{
> +	ap->link.flags |= ATA_LFLAG_NO_HRST;
> +	ata_sff_error_handler(ap);
> +	ap->link.flags&= ~ATA_LFLAG_NO_HRST;

why do you mess with ATA_LFLAG_NO_HRST in this way?


> +	/* Get SATA interrupt number */
> +	irq = irq_of_parse_and_map(ofdev->node, 0);
> +	if (irq == NO_IRQ) {
> +		dev_err(&ofdev->dev, "no SATA DMA irq\n");
> +		err = -ENODEV;
> +		goto error_out;
> +	}
> +
> +	/*
> +	 * Now, register with libATA core, this will also initiate the
> +	 * device discovery process, invoking our port_start() handler&
> +	 * error_handler() to execute a dummy Softreset EH session
> +	 */
> +	ata_host_activate(host, irq, sata_dwc_isr, 0,&sata_dwc_sht);

handle ata_host_activate failure

^ permalink raw reply

* [PATCHv3 2/3] powerpc: Switch VIO Bus PM to use generic helpers
From: Brian King @ 2010-05-14 22:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1273556129.21352.3.camel@pasglop>


Switch to use the generic power management helpers.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 arch/powerpc/kernel/vio.c |   25 +------------------------
 1 file changed, 1 insertion(+), 24 deletions(-)

diff -puN arch/powerpc/kernel/vio.c~powerpc_vio_bus_pm2 arch/powerpc/kernel/vio.c
--- powerpc.git/arch/powerpc/kernel/vio.c~powerpc_vio_bus_pm2	2010-05-11 09:49:58.000000000 -0500
+++ powerpc.git-bjking1/arch/powerpc/kernel/vio.c	2010-05-11 09:50:44.000000000 -0500
@@ -1381,29 +1381,6 @@ static int vio_hotplug(struct device *de
 	return 0;
 }
 
-static int vio_pm_suspend(struct device *dev)
-{
-	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-	if (pm && pm->suspend)
-		return pm->suspend(dev);
-	return 0;
-}
-
-static int vio_pm_resume(struct device *dev)
-{
-	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-	if (pm && pm->resume)
-		return pm->resume(dev);
-	return 0;
-}
-
-const struct dev_pm_ops vio_dev_pm_ops = {
-	.suspend = vio_pm_suspend,
-	.resume = vio_pm_resume,
-};
-
 static struct bus_type vio_bus_type = {
 	.name = "vio",
 	.dev_attrs = vio_dev_attrs,
@@ -1411,7 +1388,7 @@ static struct bus_type vio_bus_type = {
 	.match = vio_bus_match,
 	.probe = vio_bus_probe,
 	.remove = vio_bus_remove,
-	.pm = &vio_dev_pm_ops,
+	.pm = GENERIC_SUBSYS_PM_OPS,
 };
 
 /**
_

^ permalink raw reply

* Re: [PATCH]460EX on-chip SATA driver <Kernel 2.6.33> < resubmission >
From: Benjamin Herrenschmidt @ 2010-05-15 23:40 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: linuxppc-dev, Rupjyoti Sarmah, linux-kernel, linux-ide, sr,
	jgarzik
In-Reply-To: <4BED8BF1.5080800@ru.mvista.com>

On Fri, 2010-05-14 at 21:44 +0400, Sergei Shtylyov wrote:
> Hello.
> 
> Rupjyoti Sarmah wrote:
> 
> > This patch enables the on-chip DWC SATA controller of the AppliedMicro processor 460EX.
> >
> > Signed-off-by: Rupjyoti Sarmah <rsarmah@appliedmicro.com> 
> > Signed-off-by: Mark Miesfeld <mmiesfeld@appliedmicro.com>
> > Signed-off-by: Prodyut Hazarika <phazarika@appliedmicro.com>
> > ---
> >  arch/powerpc/boot/dts/canyonlands.dts |    8 +
> >  drivers/ata/Kconfig                   |    9 +
> >  drivers/ata/Makefile                  |    1 +
> >  drivers/ata/sata_dwc.c                | 1827 +++++++++++++++++++++++++++++++++
> >  4 files changed, 1845 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/ata/sata_dwc.c
> >
> > diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
> > index cd56bb5..d3b2c99 100644
> > --- a/arch/powerpc/boot/dts/canyonlands.dts
> > +++ b/arch/powerpc/boot/dts/canyonlands.dts
> > @@ -163,6 +163,14 @@
> >  			interrupts = <0x1e 4>;
> >  		};
> >  
> > +		SATA0: sata@bffd1000 {
> > +                        compatible = "amcc,sata-460ex";
> > +			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
> > +                        interrupt-parent = <&UIC3>;
> > +                        interrupts = <0x0 0x4       /* SATA */
> > +                                      0x5 0x4>;     /* AHBDMA */
> > +                };
> > +
> >  		POB0: opb {
> >  			compatible = "ibm,opb-460ex", "ibm,opb";
> >  			#address-cells = <1>;
> >   
> 
>    Please put the device tree update in a separate patch to go thru the 
> PowerPC tree.

Additionally, the boot wrapper should probably either remove the node or
at least use a status property "ok" / "disabled" to represent whether
the board is configured for SATA or PCIe x1...

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] media/IR: Add missing include file to rc-map.c
From: Mauro Carvalho Chehab @ 2010-05-16  1:54 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: linux-mips, Paul Mundt, linux-sh, linux-kernel, David H?rdeman,
	linuxppc-dev, linux-m68k, linux-next, linux-media
In-Reply-To: <201005141326.52099.PeterHuewe@gmx.de>

Peter Hüwe wrote:
> From: Peter Huewe <peterhuewe@gmx.de>
> 
> This patch adds a missing include linux/delay.h to prevent
> build failures[1-5]
> 
> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
> ---
> Forwarded to linux-next mailing list - 
> breakage still exists in linux-next of 20100514 - please apply
> 
> KernelVersion: linux-next-20100505

Sorry for not answer earlier. I was traveling. Anyway, this
patch got applied on May, 12:

http://git.kernel.org/?p=linux/kernel/git/mchehab/linux-next.git;a=commitdiff;h=4ace7aa2998b2974948f1948a61a5d348ddae472

> 
> References:
> [1] http://kisskb.ellerman.id.au/kisskb/buildresult/2571452/
> [2] http://kisskb.ellerman.id.au/kisskb/buildresult/2571188/
> [3] http://kisskb.ellerman.id.au/kisskb/buildresult/2571479/
> [4] http://kisskb.ellerman.id.au/kisskb/buildresult/2571429/
> [5] http://kisskb.ellerman.id.au/kisskb/buildresult/2571432/
> 
> drivers/media/IR/rc-map.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c
> index caf6a27..46a8f15 100644
> --- a/drivers/media/IR/rc-map.c
> +++ b/drivers/media/IR/rc-map.c
> @@ -14,6 +14,7 @@
>  
>  #include <media/ir-core.h>
>  #include <linux/spinlock.h>
> +#include <linux/delay.h>
>  
>  /* Used to handle IR raw handler extensions */
>  static LIST_HEAD(rc_map_list);


-- 

Cheers,
Mauro

^ permalink raw reply

* Re: [Patch v2 1/2] 5200/mpc: improve i2c bus error recovery
From: Albrecht Dreß @ 2010-05-16 17:47 UTC (permalink / raw)
  To: Grant Likely
  Cc: Linux PPC Development, Devicetree Discussions,
	Ben Dooks (embedded platforms), Ira W. Snyder
In-Reply-To: <h2mfa686aa41005061106ofda766f5z64c4f631eaded414@mail.gmail.com>

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

Am 06.05.10 20:06 schrieb(en) Grant Likely:
> > I think, though, the whole stuff has been discussed in depth in February, so
> > I do not understand why it's still pending as "new".  Grant, did we miss
> > something here?
> 
> I generally let subsystem maintainers pick up the device driver
> patches for embedded platforms I'm responsible for unless I'm asked to
> do otherwise.  I think ben has asked me to take these through my tree.

That's <http://git.secretlab.ca/?p=linux-2.6.git;a=shortlog>, isn't it?  Hmmm, didn't find it there... :-/

Best, Albrecht.

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

^ permalink raw reply

* Re: [Uclinux-dist-devel] Config Items appearing twice in same Kconfig file?
From: Mike Frysinger @ 2010-05-17  5:13 UTC (permalink / raw)
  To: Christoph Egger
  Cc: linux-ia64, vamos, Jesse Barnes, Timo Teras, Chen Liqin,
	Paul Mackerras, H. Peter Anvin, Lennox Wu, Jesper Nilsson,
	Pekka Savola (ipv6), x86, James Morris, Ingo Molnar,
	Alexey Kuznetsov, Matt Turner, Fenghua Yu, Mike Frysinger,
	Arnd Bergmann, Graf Yang, Mikael Starvik, Ivan Kokshaysky,
	Thomas Gleixner, Arjan van de Ven, Richard Henderson,
	Karsten Keil, Tony Luck, linux-cris-kernel, linuxppc-dev,
	Hideaki YOSHIFUJI, netdev, linux-kernel, Patrick McHardy,
	FUJITA Tomonori, linux-alpha, uclinux-dist-devel, Andrew Morton,
	David S. Miller
In-Reply-To: <20100512144017.GA722@faui48a.informatik.uni-erlangen.de>

On Wed, May 12, 2010 at 10:40, Christoph Egger wrote:
> =C2=A0 =C2=A0 =C2=A02 arch/blackfin/Kconfig:config MEM_MT48LC32M8A2_75

thanks, i'll get this simple bug fixed
-mike

^ permalink raw reply

* [PATCH 1/2] powerpc: Remove ibm,smt-snooze-delay OF property
From: Anton Blanchard @ 2010-05-17  6:01 UTC (permalink / raw)
  To: benh, nfont; +Cc: linuxppc-dev


I'm not sure why we have code for parsing an ibm,smt-snooze-delay OF
property. Since we have a smt-snooze-delay= boot option and we can
also set it at runtime via sysfs, it should be safe to get rid of
this code.

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

Index: powerpc.git/arch/powerpc/kernel/sysfs.c
===================================================================
--- powerpc.git.orig/arch/powerpc/kernel/sysfs.c	2010-05-17 15:05:29.917208655 +1000
+++ powerpc.git/arch/powerpc/kernel/sysfs.c	2010-05-17 15:18:24.164704601 +1000
@@ -67,33 +67,6 @@ static ssize_t show_smt_snooze_delay(str
 static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
 		   store_smt_snooze_delay);
 
-/* Only parse OF options if the matching cmdline option was not specified */
-static int smt_snooze_cmdline;
-
-static int __init smt_setup(void)
-{
-	struct device_node *options;
-	const unsigned int *val;
-	unsigned int cpu;
-
-	if (!cpu_has_feature(CPU_FTR_SMT))
-		return -ENODEV;
-
-	options = of_find_node_by_path("/options");
-	if (!options)
-		return -ENODEV;
-
-	val = of_get_property(options, "ibm,smt-snooze-delay", NULL);
-	if (!smt_snooze_cmdline && val) {
-		for_each_possible_cpu(cpu)
-			per_cpu(smt_snooze_delay, cpu) = *val;
-	}
-
-	of_node_put(options);
-	return 0;
-}
-__initcall(smt_setup);
-
 static int __init setup_smt_snooze_delay(char *str)
 {
 	unsigned int cpu;
@@ -102,8 +75,6 @@ static int __init setup_smt_snooze_delay
 	if (!cpu_has_feature(CPU_FTR_SMT))
 		return 1;
 
-	smt_snooze_cmdline = 1;
-
 	if (get_option(&str, &snooze)) {
 		for_each_possible_cpu(cpu)
 			per_cpu(smt_snooze_delay, cpu) = snooze;

^ permalink raw reply

* [PATCH 2/2] powerpc: Use smt_snooze_delay=-1 to always busy loop
From: Anton Blanchard @ 2010-05-17  6:02 UTC (permalink / raw)
  To: benh, nfont; +Cc: linuxppc-dev
In-Reply-To: <20100517060128.GC13509@kryten>


Right now if we want to busy loop and not give up any time to the hypervisor
we put a very large value into smt_snooze_delay. This is sometimes useful
when running a single partition and you want to avoid any latencies due
to the hypervisor or CPU power state transitions. While this works, it's a bit
ugly - how big a number is enough now we have NO_HZ and can be idle for a very
long time.

The patch below makes smt_snooze_delay signed, and a negative value means loop
forever:

echo -1 > /sys/devices/system/cpu/cpu0/smt_snooze_delay

This change shouldn't affect the existing userspace tools (eg ppc64_cpu), but
I'm cc-ing Nathan just to be sure.

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

Index: powerpc.git/arch/powerpc/kernel/sysfs.c
===================================================================
--- powerpc.git.orig/arch/powerpc/kernel/sysfs.c	2010-05-17 15:18:24.164704601 +1000
+++ powerpc.git/arch/powerpc/kernel/sysfs.c	2010-05-17 15:18:26.207205125 +1000
@@ -35,7 +35,7 @@ static DEFINE_PER_CPU(struct cpu, cpu_de
 #ifdef CONFIG_PPC64
 
 /* Time in microseconds we delay before sleeping in the idle loop */
-DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 };
+DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
 
 static ssize_t store_smt_snooze_delay(struct sys_device *dev,
 				      struct sysdev_attribute *attr,
@@ -44,9 +44,9 @@ static ssize_t store_smt_snooze_delay(st
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 	ssize_t ret;
-	unsigned long snooze;
+	long snooze;
 
-	ret = sscanf(buf, "%lu", &snooze);
+	ret = sscanf(buf, "%ld", &snooze);
 	if (ret != 1)
 		return -EINVAL;
 
@@ -61,7 +61,7 @@ static ssize_t show_smt_snooze_delay(str
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 
-	return sprintf(buf, "%lu\n", per_cpu(smt_snooze_delay, cpu->sysdev.id));
+	return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->sysdev.id));
 }
 
 static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
@@ -70,15 +70,14 @@ static SYSDEV_ATTR(smt_snooze_delay, 064
 static int __init setup_smt_snooze_delay(char *str)
 {
 	unsigned int cpu;
-	int snooze;
+	long snooze;
 
 	if (!cpu_has_feature(CPU_FTR_SMT))
 		return 1;
 
-	if (get_option(&str, &snooze)) {
-		for_each_possible_cpu(cpu)
-			per_cpu(smt_snooze_delay, cpu) = snooze;
-	}
+	snooze = simple_strtol(str, NULL, 10);
+	for_each_possible_cpu(cpu)
+		per_cpu(smt_snooze_delay, cpu) = snooze;
 
 	return 1;
 }
Index: powerpc.git/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- powerpc.git.orig/arch/powerpc/platforms/pseries/setup.c	2010-05-17 15:05:29.827204407 +1000
+++ powerpc.git/arch/powerpc/platforms/pseries/setup.c	2010-05-17 15:18:26.207205125 +1000
@@ -496,13 +496,14 @@ static int __init pSeries_probe(void)
 }
 
 
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+DECLARE_PER_CPU(long, smt_snooze_delay);
 
 static void pseries_dedicated_idle_sleep(void)
 { 
 	unsigned int cpu = smp_processor_id();
 	unsigned long start_snooze;
 	unsigned long in_purr, out_purr;
+	long snooze = __get_cpu_var(smt_snooze_delay);
 
 	/*
 	 * Indicate to the HV that we are idle. Now would be
@@ -517,13 +518,12 @@ static void pseries_dedicated_idle_sleep
 	 * has been checked recently.  If we should poll for a little
 	 * while, do so.
 	 */
-	if (__get_cpu_var(smt_snooze_delay)) {
-		start_snooze = get_tb() +
-			__get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec;
+	if (snooze) {
+		start_snooze = get_tb() + snooze * tb_ticks_per_usec;
 		local_irq_enable();
 		set_thread_flag(TIF_POLLING_NRFLAG);
 
-		while (get_tb() < start_snooze) {
+		while ((snooze < 0) || (get_tb() < start_snooze)) {
 			if (need_resched() || cpu_is_offline(cpu))
 				goto out;
 			ppc64_runlatch_off();

^ permalink raw reply

* [PATCH 1/3] powerpc: numa: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
From: Anton Blanchard @ 2010-05-17  6:19 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev


I noticed /proc/sys/vm/zone_reclaim_mode was 0 on a ppc64 NUMA box. It gets
enabled via this:

        /*
         * If another node is sufficiently far away then it is better
         * to reclaim pages in a zone before going off node.
         */
        if (distance > RECLAIM_DISTANCE)
                zone_reclaim_mode = 1;

Since we use the default value of 20 for REMOTE_DISTANCE and 20 for
RECLAIM_DISTANCE it never kicks in.

The local to remote bandwidth ratios can be quite large on System p
machines so it makes sense for us to reclaim clean pagecache locally before
going off node.

The patch below sets a smaller value for RECLAIM_DISTANCE and thus enables
zone reclaim.

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

Index: powerpc.git/arch/powerpc/include/asm/topology.h
===================================================================
--- powerpc.git.orig/arch/powerpc/include/asm/topology.h	2010-05-17 12:56:02.000000000 +1000
+++ powerpc.git/arch/powerpc/include/asm/topology.h	2010-05-17 15:01:37.514703571 +1000
@@ -18,6 +18,16 @@ struct device_node;
  */
 #define RECLAIM_DISTANCE 10
 
+/*
+ * Before going off node we want the VM to try and reclaim from the local
+ * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
+ * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
+ * 20, we never reclaim and go off node straight away.
+ *
+ * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ */
+#define RECLAIM_DISTANCE 10
+
 #include <asm/mmzone.h>
 
 static inline int cpu_to_node(int cpu)

^ permalink raw reply

* [PATCH 2/3] powerpc: numa: Use ibm,architecture-vec-5 to detect form 1 affinity
From: Anton Blanchard @ 2010-05-17  6:21 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <20100517061956.GE13509@kryten>


I've been told that the architected way to determine we are in form 1
affinity mode is by reading the ibm,architecture-vec-5 property which
mirrors the layout of the fifth byte of the ibm,client-architecture
structure.

Eventually we may want to parse the ibm,architecture-vec-5 and create
FW_FEATURE_* bits. 

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

Index: powerpc.git/arch/powerpc/mm/numa.c
===================================================================
--- powerpc.git.orig/arch/powerpc/mm/numa.c	2010-05-17 12:56:02.000000000 +1000
+++ powerpc.git/arch/powerpc/mm/numa.c	2010-05-17 15:01:40.345954329 +1000
@@ -271,7 +271,8 @@ static int __init find_min_common_depth(
 	const unsigned int *ref_points;
 	struct device_node *rtas_root;
 	unsigned int len;
-	struct device_node *options;
+	struct device_node *chosen;
+	const char *vec5;
 
 	rtas_root = of_find_node_by_path("/rtas");
 
@@ -289,14 +290,17 @@ static int __init find_min_common_depth(
 			"ibm,associativity-reference-points", &len);
 
 	/*
-	 * For type 1 affinity information we want the first field
+	 * For form 1 affinity information we want the first field
 	 */
-	options = of_find_node_by_path("/options");
-	if (options) {
-		const char *str;
-		str = of_get_property(options, "ibm,associativity-form", NULL);
-		if (str && !strcmp(str, "1"))
-                        index = 0;
+#define VEC5_AFFINITY_BYTE	5
+#define VEC5_AFFINITY		0x80
+	chosen = of_find_node_by_path("/chosen");
+	if (chosen) {
+		vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
+		if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
+			dbg("Using form 1 affinity\n");
+			index = 0;
+		}
 	}
 
 	if ((len >= 2 * sizeof(unsigned int)) && ref_points) {

^ permalink raw reply

* [PATCH 3/3] powerpc: numa: Use form 1 affinity to setup node distance
From: Anton Blanchard @ 2010-05-17  6:22 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <20100517062157.GA25848@kryten>


Form 1 affinity allows multiple entries in ibm,associativity-reference-points
which represent affinity domains in decreasing order of importance. The
Linux concept of a node is always the first entry, but using the other
values as an input to node_distance() allows the memory allocator to make
better decisions on which node to go first when local memory has been
exhausted.

We keep things simple and create an array indexed by NUMA node, capped at
4 entries. Each time we lookup an associativity property we initialise
the array which is overkill, but since we should only hit this path during
boot it didn't seem worth adding a per node valid bit.

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

Index: powerpc.git/arch/powerpc/mm/numa.c
===================================================================
--- powerpc.git.orig/arch/powerpc/mm/numa.c	2010-05-17 15:01:40.345954329 +1000
+++ powerpc.git/arch/powerpc/mm/numa.c	2010-05-17 15:01:43.334704959 +1000
@@ -42,6 +42,12 @@ EXPORT_SYMBOL(node_data);
 
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
+static int form1_affinity;
+
+#define MAX_DISTANCE_REF_POINTS 4
+static int distance_ref_points_depth;
+static const unsigned int *distance_ref_points;
+static int distance_lookup_table[MAX_NUMNODES][MAX_DISTANCE_REF_POINTS];
 
 /*
  * Allocate node_to_cpumask_map based on number of available nodes
@@ -204,6 +210,39 @@ static const u32 *of_get_usable_memory(s
 	return prop;
 }
 
+int __node_distance(int a, int b)
+{
+	int i;
+	int distance = LOCAL_DISTANCE;
+
+	if (!form1_affinity)
+		return distance;
+
+	for (i = 0; i < distance_ref_points_depth; i++) {
+		if (distance_lookup_table[a][i] == distance_lookup_table[b][i])
+			break;
+
+		/* Double the distance for each NUMA level */
+		distance *= 2;
+	}
+
+	return distance;
+}
+
+static void initialize_distance_lookup_table(int nid,
+		const unsigned int *associativity)
+{
+	int i;
+
+	if (!form1_affinity)
+		return;
+
+	for (i = 0; i < distance_ref_points_depth; i++) {
+		distance_lookup_table[nid][i] =
+			associativity[distance_ref_points[i]];
+	}
+}
+
 /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
  * info is found.
  */
@@ -225,6 +264,10 @@ static int of_node_to_nid_single(struct 
 	/* POWER4 LPAR uses 0xffff as invalid node */
 	if (nid == 0xffff || nid >= MAX_NUMNODES)
 		nid = -1;
+
+	if (nid > 0 && tmp[0] >= distance_ref_points_depth)
+		initialize_distance_lookup_table(nid, tmp);
+
 out:
 	return nid;
 }
@@ -251,26 +294,10 @@ int of_node_to_nid(struct device_node *d
 }
 EXPORT_SYMBOL_GPL(of_node_to_nid);
 
-/*
- * In theory, the "ibm,associativity" property may contain multiple
- * associativity lists because a resource may be multiply connected
- * into the machine.  This resource then has different associativity
- * characteristics relative to its multiple connections.  We ignore
- * this for now.  We also assume that all cpu and memory sets have
- * their distances represented at a common level.  This won't be
- * true for hierarchical NUMA.
- *
- * In any case the ibm,associativity-reference-points should give
- * the correct depth for a normal NUMA system.
- *
- * - Dave Hansen <haveblue@us.ibm.com>
- */
 static int __init find_min_common_depth(void)
 {
-	int depth, index;
-	const unsigned int *ref_points;
+	int depth;
 	struct device_node *rtas_root;
-	unsigned int len;
 	struct device_node *chosen;
 	const char *vec5;
 
@@ -280,18 +307,28 @@ static int __init find_min_common_depth(
 		return -1;
 
 	/*
-	 * this property is 2 32-bit integers, each representing a level of
-	 * depth in the associativity nodes.  The first is for an SMP
-	 * configuration (should be all 0's) and the second is for a normal
-	 * NUMA configuration.
+	 * This property is a set of 32-bit integers, each representing
+	 * an index into the ibm,associativity nodes.
+	 *
+	 * With form 0 affinity the first integer is for an SMP configuration
+	 * (should be all 0's) and the second is for a normal NUMA
+	 * configuration. We have only one level of NUMA.
+	 *
+	 * With form 1 affinity the first integer is the most significant
+	 * NUMA boundary and the following are progressively less significant
+	 * boundaries. There can be more than one level of NUMA.
 	 */
-	index = 1;
-	ref_points = of_get_property(rtas_root,
-			"ibm,associativity-reference-points", &len);
+	distance_ref_points = of_get_property(rtas_root,
+					"ibm,associativity-reference-points",
+					&distance_ref_points_depth);
+
+	if (!distance_ref_points) {
+		dbg("NUMA: ibm,associativity-reference-points not found.\n");
+		goto err;
+	}
+
+	distance_ref_points_depth /= sizeof(int);
 
-	/*
-	 * For form 1 affinity information we want the first field
-	 */
 #define VEC5_AFFINITY_BYTE	5
 #define VEC5_AFFINITY		0x80
 	chosen = of_find_node_by_path("/chosen");
@@ -299,19 +336,38 @@ static int __init find_min_common_depth(
 		vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
 		if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
 			dbg("Using form 1 affinity\n");
-			index = 0;
+			form1_affinity = 1;
 		}
 	}
 
-	if ((len >= 2 * sizeof(unsigned int)) && ref_points) {
-		depth = ref_points[index];
+	if (form1_affinity) {
+		depth = distance_ref_points[0];
 	} else {
-		dbg("NUMA: ibm,associativity-reference-points not found.\n");
-		depth = -1;
+		if (distance_ref_points_depth < 2) {
+			printk(KERN_WARNING "NUMA: "
+				"short ibm,associativity-reference-points\n");
+			goto err;
+		}
+
+		depth = distance_ref_points[1];
 	}
-	of_node_put(rtas_root);
 
+	/*
+	 * Warn and cap if the hardware supports more than
+	 * MAX_DISTANCE_REF_POINTS domains.
+	 */
+	if (distance_ref_points_depth > MAX_DISTANCE_REF_POINTS) {
+		printk(KERN_WARNING "NUMA: distance array capped at "
+			"%d entries\n", MAX_DISTANCE_REF_POINTS);
+		distance_ref_points_depth = MAX_DISTANCE_REF_POINTS;
+	}
+
+	of_node_put(rtas_root);
 	return depth;
+
+err:
+	of_node_put(rtas_root);
+	return -1;
 }
 
 static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells)
Index: powerpc.git/arch/powerpc/include/asm/topology.h
===================================================================
--- powerpc.git.orig/arch/powerpc/include/asm/topology.h	2010-05-17 15:01:37.514703571 +1000
+++ powerpc.git/arch/powerpc/include/asm/topology.h	2010-05-17 15:01:43.334704959 +1000
@@ -87,6 +87,9 @@ static inline int pcibus_to_node(struct 
 	.balance_interval	= 1,					\
 }
 
+extern int __node_distance(int, int);
+#define node_distance(a, b) __node_distance(a, b)
+
 extern void __init dump_numa_cpu_topology(void);
 
 extern int sysfs_add_device_to_node(struct sys_device *dev, int nid);

^ permalink raw reply

* [PATCH 2/3] powerpc: numa: Use ibm,architecture-vec-5 to detect form 1 affinity
From: Anton Blanchard @ 2010-05-17  6:28 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <20100517062157.GA25848@kryten>


I've been told that the architected way to determine we are in form 1
affinity mode is by reading the ibm,architecture-vec-5 property which
mirrors the layout of the fifth vector of the ibm,client-architecture
structure.

Eventually we may want to parse the ibm,architecture-vec-5 and create
FW_FEATURE_* bits. 

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

v2: I said "fifth byte of the ibm,client-architecture" when I should have
said "fifth vector of the ibm,client-architecture"

Index: powerpc.git/arch/powerpc/mm/numa.c
===================================================================
--- powerpc.git.orig/arch/powerpc/mm/numa.c	2010-05-17 12:56:02.000000000 +1000
+++ powerpc.git/arch/powerpc/mm/numa.c	2010-05-17 15:01:40.345954329 +1000
@@ -271,7 +271,8 @@ static int __init find_min_common_depth(
 	const unsigned int *ref_points;
 	struct device_node *rtas_root;
 	unsigned int len;
-	struct device_node *options;
+	struct device_node *chosen;
+	const char *vec5;
 
 	rtas_root = of_find_node_by_path("/rtas");
 
@@ -289,14 +290,17 @@ static int __init find_min_common_depth(
 			"ibm,associativity-reference-points", &len);
 
 	/*
-	 * For type 1 affinity information we want the first field
+	 * For form 1 affinity information we want the first field
 	 */
-	options = of_find_node_by_path("/options");
-	if (options) {
-		const char *str;
-		str = of_get_property(options, "ibm,associativity-form", NULL);
-		if (str && !strcmp(str, "1"))
-                        index = 0;
+#define VEC5_AFFINITY_BYTE	5
+#define VEC5_AFFINITY		0x80
+	chosen = of_find_node_by_path("/chosen");
+	if (chosen) {
+		vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
+		if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
+			dbg("Using form 1 affinity\n");
+			index = 0;
+		}
 	}
 
 	if ((len >= 2 * sizeof(unsigned int)) && ref_points) {

^ permalink raw reply

* Re: [PATCH v3 3/3] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Richard Cochran @ 2010-05-17  8:27 UTC (permalink / raw)
  To: Scott Wood; +Cc: netdev, devicetree-discuss, linuxppc-dev
In-Reply-To: <4BED8C91.8020107@freescale.com>

On Fri, May 14, 2010 at 12:46:57PM -0500, Scott Wood wrote:
> On 05/14/2010 11:46 AM, Richard Cochran wrote:
> >diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
> 
> Get rid of both device_type and model, and specify a compatible
> string instead (e.g. "fsl,etsec-ptp").

Okay, will do. I really am at a loss at understanding all the rules in
the whole device tree world. I just tried to follow
Documentation/powerpc and what is already present in the kernel.

> Or perhaps this should just be some additional properties on the
> existing gianfar nodes, rather than presenting it as a separate
> device?  How do you associate a given ptp block with the
> corresponding gianfar node?

There only one PTP clock. Its registers repeat in each port's memory
space, but you are only supposed to touch the first set of PTP
registers. If you consider how PTP works, there can never be per port
clocks, since this would make it impossible to make a boundary clock,
for example.

The whole idea of this PTP clock framework is to keep the clock
drivers separate from the MAC drivers, even when they use the same
hardware. The functionality is logically divided into two parts. The
MAC provides time stamps, and the clock provides a way to control its
offset and frequency.

Up until this point, people have simply hacked new private ioctls into
the driver for each MAC that supports PTP. That is not a good long
term solution for PTP support in Linux.

In general, I think it will not be hard to keep the MAC and the clock
drivers from stepping on each other's toes. The eTSEC hardware is
certainly able to be used in this way.

> If there are differences in ptp implementation between different
> versions of etsec, can the ptp driver see the etsec version
> register?

There are no differences (that I know of) in how the PTP clocks
work. I have in house the mpc8313, the mpc8572, and the p2020. The
mpc8572 appears to lack some of the TMR_CTRL bits, but this is
probably a documentation bug. I will check it.

> >+  - tclk_period  Timer reference clock period in nanoseconds.
> >+  - tmr_prsc     Prescaler, divides the output clock.
> >+  - tmr_add      Frequency compensation value.
> >+  - cksel        0= external clock, 1= eTSEC system clock, 3= RTC clock input.
> >+                 Currently the driver only supports choice "1".
> >+  - tmr_fiper1   Fixed interval period pulse generator.
> >+  - tmr_fiper2   Fixed interval period pulse generator.
> 
> Dashes are more typical in OF names than underscores, and it's
> generally better to be a little more verbose -- these aren't local
> loop iterators.

The names come from the register mnemonics from the documentation. I
prefer to use the same names as is found in the manuals. That way, a
person working with docu in hand will have an easier job.

> They should probably have an "fsl,ptp-" prefix as well.

Okay, but must I then change the following code in order to find them?
Does adding the prefix just mean that I also add it to my search
strings, or is it preprocessed (stripped) somehow?

static int get_of_u32(struct device_node *node, char *str, u32 *val)
{
	int plen;
	const u32 *prop = of_get_property(node, str, &plen);

	if (!prop || plen != sizeof(*prop))
	   return -1;
	   *val = *prop;
	   return 0;
}
...
	if (get_of_u32(node, "tclk_period",&etsects->tclk_period) ||
	    get_of_u32(node, "tmr_prsc",&etsects->tmr_prsc) ||
	    get_of_u32(node, "tmr_add",&etsects->tmr_add) ||
	    get_of_u32(node, "cksel",&etsects->cksel) ||
	    get_of_u32(node, "tmr_fiper1",&etsects->tmr_fiper1) ||
	    get_of_u32(node, "tmr_fiper2",&etsects->tmr_fiper2))
		return -ENODEV;

> >+  These properties set the operational parameters for the PTP
> >+  clock. You must choose these carefully for the clock to work right.
> 
> Do these values describe the way the hardware is, or how it's been
> configured by firmware, or a set of values that are clearly optimal
> for this particular board?  If it's just configuration for the Linux
> driver, that could reasonably differ based on what a given user or
> OS will want, the device tree probably isn't the right place for it.

The values are related to the board. One important parameter is the
input clock, and the rest reflect some engineering decisions/tradeoffs
related to the signals to and from the PTP clock. There is not just
one "optimal" choice, so I wanted to let the designer set the
values. In any case, the parameters are definitely related to the
board (not to the cpu or to linux), so I think the device tree is the
right place for them.

> This one has 3 interrupts?  The driver supports only two.

The documentation does not specify the IRQ line that each event
belongs to. After some trial and error, it appears that all of the
ancillary clock interrupts arrive on the first interrupt. The other
lines (one per port) must be for the Tx/Rx packet time stamp
indication, but we don't need these for the clock or for the MAC.

I'll just reduce the driver to one interrupt.

> >+/* Private globals */
> >+static struct ptp_clock *gianfar_clock;
> 
> Do you not support more than one of these?
> 
> >+static struct etsects the_clock;
> 
> "The" clock?  As oppsed to the "other" clock one line above? :-)

The 'gianfar_clock' variable holds the returned instance from the
class driver, while 'the_clock' is the driver's private data (and
there can only be one driver).

I'll combine these into one struct to make it more clear and less
funny sounding.

> >+	return IRQ_HANDLED;
> 
> Should only return IRQ_HANDLED if you found an event.

Okay.

> >+	if (get_of_u32(node, "tclk_period",&etsects->tclk_period) ||
> >+	    get_of_u32(node, "tmr_prsc",&etsects->tmr_prsc) ||
> >+	    get_of_u32(node, "tmr_add",&etsects->tmr_add) ||
> >+	    get_of_u32(node, "cksel",&etsects->cksel) ||
> >+	    get_of_u32(node, "tmr_fiper1",&etsects->tmr_fiper1) ||
> >+	    get_of_u32(node, "tmr_fiper2",&etsects->tmr_fiper2))
> >+		return -ENODEV;
> 
> Might want to print an error so the user knows what's missing.

Okay.

> You've got two IRQs, with the same handler, and the same dev_id?
> From the manual it looks like there's one PTP interrupt per eTSEC
> (which would explain 3 interrupts on p2020).

Will reduce to just one IRQ.

> >+static struct of_device_id match_table[] = {
> >+	{ .type = "ptp_clock" },
> >+	{},
> >+};
> 
> This driver controls every possible PTP implementation?

No, I only want to match with the eTSEC clock device. Given the
compatible string above ("fsl,etsec-ptp"), what is the correct way to
do this? (pointer to an existing driver to emulate would be enough)

Thanks for your help,

Richard

^ permalink raw reply

* Re: [RFC][PATCH 0/12] KVM, x86, ppc, asm-generic: moving dirty bitmaps to user space
From: Takuya Yoshikawa @ 2010-05-17  9:06 UTC (permalink / raw)
  To: Avi Kivity
  Cc: linux-arch, arnd, kvm, kvm-ia64, fernando, mtosatti, agraf,
	kvm-ppc, linux-kernel, linuxppc-dev, Takuya Yoshikawa
In-Reply-To: <4BEBE6D0.8020000@redhat.com>


> User allocated bitmaps have the advantage of reducing pinned memory.
> However we have plenty more pinned memory allocated in memory slots, so
> by itself, user allocated bitmaps don't justify this change.

In that sense, what do you think about the question I sent last week?

=== REPOST 1 ===
 >>
 >> mark_page_dirty is called with the mmu_lock spinlock held in set_spte.
 >> Must find a way to move it outside of the spinlock section.
 >>
 >
 > Oh, it's a serious problem. I have to consider it.

Avi, Marcelo,

Sorry but I have to say that mmu_lock spin_lock problem was completely out of
my mind. Although I looked through the code, it seems not easy to move the
set_bit_user to outside of spinlock section without breaking the semantics of
its protection.

So this may take some time to solve.

But personally, I want to do something for x86's "vmallc() every time" problem
even though moving dirty bitmaps to user space cannot be achieved soon.

In that sense, do you mind if we do double buffering without moving dirty bitmaps to
user space?

I know that the resource for vmalloc() is precious for x86 but even now, at the timing
of get_dirty_log, we use the same amount of memory as double buffering.
=== 1 END ===


>
> Perhaps if we optimize memory slot write protection (I have some ideas
> about this) we can make the performance improvement more pronounced.
>

It's really nice!

Even now we can measure the performance improvement by introducing switch ioctl
when guest is relatively idle, so the combination will be really effective!

=== REPOST 2 ===
 >>
 >> Can you post such a test, for an idle large guest?
 >
 > OK, I'll do!


Result of "low workload test" (running top during migration) first,

4GB guest
picked up slots[1](len=3757047808) only
*****************************************
     get.org     get.opt    switch.opt

     1060875     310292     190335
     1076754     301295     188600
      655504     318284     196029
      529769     301471        325
      694796      70216     221172
      651868     353073     196184
      543339     312865     213236
     1061938      72785     203090
      689527     323901     249519
      621364     323881        473
     1063671      70703     192958
      915903     336318     174008
     1046462     332384        782
     1037942      72783     190655
      680122     318305     243544
      688156     314935     193526
      558658     265934     190550
      652454     372135     196270
      660140      68613        352
     1101947     378642     186575
         ...        ...        ...
*****************************************

As expected we've got the difference more clearly.

In this case, switch.opt reduced 1/3 (.1 msec) compared to get.opt
for each iteration.

And when the slot is cleaner, the ratio is bigger.
=== 2 END ===

^ permalink raw reply

* Re: [PATCH]460EX on-chip SATA driver <Kernel 2.6.33> < resubmission >
From: Stefan Roese @ 2010-05-17 10:06 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, linux-kernel
  Cc: linux-ide, Rupjyoti Sarmah, Sergei Shtylyov, linuxppc-dev
In-Reply-To: <1273966828.21352.670.camel@pasglop>

Hi Ben,

On Sunday 16 May 2010 01:40:28 Benjamin Herrenschmidt wrote:
> > > +		SATA0: sata@bffd1000 {
> > > +                        compatible = "amcc,sata-460ex";
> > > +			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
> > > +                        interrupt-parent = <&UIC3>;
> > > +                        interrupts = <0x0 0x4       /* SATA */
> > > +                                      0x5 0x4>;     /* AHBDMA */
> > > +                };
> > > +
> > > 
> > >  		POB0: opb {
> > >  		
> > >  			compatible = "ibm,opb-460ex", "ibm,opb";
> > >  			#address-cells = <1>;
> >    
> >    Please put the device tree update in a separate patch to go thru the
> > 
> > PowerPC tree.
> 
> Additionally, the boot wrapper should probably either remove the node or
> at least use a status property "ok" / "disabled" to represent whether
> the board is configured for SATA or PCIe x1...

U-Boot already sets the "status" property of the PCIe or SATA node 
accordingly. Just let me know if this doesn't work for you.

Cheers,
Stefan

^ permalink raw reply

* Re: [PATCH]460EX on-chip SATA driver <Kernel 2.6.33> < resubmission >
From: Benjamin Herrenschmidt @ 2010-05-17 10:36 UTC (permalink / raw)
  To: Stefan Roese
  Cc: linux-ide, Rupjyoti Sarmah, linux-kernel, Sergei Shtylyov,
	linuxppc-dev
In-Reply-To: <201005171206.47566.sr@denx.de>


> > Additionally, the boot wrapper should probably either remove the node or
> > at least use a status property "ok" / "disabled" to represent whether
> > the board is configured for SATA or PCIe x1...
> 
> U-Boot already sets the "status" property of the PCIe or SATA node 
> accordingly. Just let me know if this doesn't work for you.

That's probably enough.

Cheers,
Ben.

^ permalink raw reply

* [PATCH] powerpc/pseries: Make request_ras_irqs() available to other pseries code
From: Mark Nelson @ 2010-05-17 12:33 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Tseng-hui Lin, engebret

At the moment only the RAS code uses event-sources interrupts (for EPOW
events and internal errors) so request_ras_irqs() (which actually requests
the event-sources interrupts) is found in ras.c and is static.

We want to be able to use event-sources interrupts in other pseries code,
so let's rename request_ras_irqs() to request_event_sources_irqs() and
move it to event_sources.c.

This will be used in an upcoming patch that adds support for IO Event
interrupts that come through as event sources.

Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
 arch/powerpc/platforms/pseries/Makefile        |    2 
 arch/powerpc/platforms/pseries/event_sources.c |   79 +++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/event_sources.h |   29 +++++++++
 arch/powerpc/platforms/pseries/ras.c           |   63 +------------------
 4 files changed, 113 insertions(+), 60 deletions(-)

Index: upstream/arch/powerpc/platforms/pseries/event_sources.c
===================================================================
--- /dev/null
+++ upstream/arch/powerpc/platforms/pseries/event_sources.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2001 Dave Engebretsen IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <asm/prom.h>
+
+#include "event_sources.h"
+
+void request_event_sources_irqs(struct device_node *np,
+				irq_handler_t handler,
+				const char *name)
+{
+	int i, index, count = 0;
+	struct of_irq oirq;
+	const u32 *opicprop;
+	unsigned int opicplen;
+	unsigned int virqs[16];
+
+	/* Check for obsolete "open-pic-interrupt" property. If present, then
+	 * map those interrupts using the default interrupt host and default
+	 * trigger
+	 */
+	opicprop = of_get_property(np, "open-pic-interrupt", &opicplen);
+	if (opicprop) {
+		opicplen /= sizeof(u32);
+		for (i = 0; i < opicplen; i++) {
+			if (count > 15)
+				break;
+			virqs[count] = irq_create_mapping(NULL, *(opicprop++));
+			if (virqs[count] == NO_IRQ)
+				printk(KERN_ERR "Unable to allocate interrupt "
+				       "number for %s\n", np->full_name);
+			else
+				count++;
+
+		}
+	}
+	/* Else use normal interrupt tree parsing */
+	else {
+		/* First try to do a proper OF tree parsing */
+		for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
+		     index++) {
+			if (count > 15)
+				break;
+			virqs[count] = irq_create_of_mapping(oirq.controller,
+							    oirq.specifier,
+							    oirq.size);
+			if (virqs[count] == NO_IRQ)
+				printk(KERN_ERR "Unable to allocate interrupt "
+				       "number for %s\n", np->full_name);
+			else
+				count++;
+		}
+	}
+
+	/* Now request them */
+	for (i = 0; i < count; i++) {
+		if (request_irq(virqs[i], handler, 0, name, NULL)) {
+			printk(KERN_ERR "Unable to request interrupt %d for "
+			       "%s\n", virqs[i], np->full_name);
+			return;
+		}
+	}
+}
+
Index: upstream/arch/powerpc/platforms/pseries/event_sources.h
===================================================================
--- /dev/null
+++ upstream/arch/powerpc/platforms/pseries/event_sources.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2001 Dave Engebretsen IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#ifndef _POWERPC_EVENT_SOURCES_H
+#define _POWERPC_EVENT_SOURCES_H
+
+#include <linux/interrupt.h>
+
+struct device_node;
+
+extern void request_event_sources_irqs(struct device_node *np,
+				       irq_handler_t handler, const char *name);
+
+#endif /* _POWERPC_EVENT_SOURCES_H */
Index: upstream/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- upstream.orig/arch/powerpc/platforms/pseries/Makefile
+++ upstream/arch/powerpc/platforms/pseries/Makefile
@@ -7,7 +7,7 @@ EXTRA_CFLAGS		+= -DDEBUG
 endif
 
 obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
-			   setup.o iommu.o ras.o \
+			   setup.o iommu.o event_sources.o ras.o \
 			   firmware.o power.o dlpar.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
Index: upstream/arch/powerpc/platforms/pseries/ras.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/pseries/ras.c
+++ upstream/arch/powerpc/platforms/pseries/ras.c
@@ -50,6 +50,7 @@
 #include <asm/firmware.h>
 
 #include "pseries.h"
+#include "event_sources.h"
 
 static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
 static DEFINE_SPINLOCK(ras_log_buf_lock);
@@ -67,63 +68,6 @@ static irqreturn_t ras_epow_interrupt(in
 static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
 
 
-static void request_ras_irqs(struct device_node *np,
-			irq_handler_t handler,
-			const char *name)
-{
-	int i, index, count = 0;
-	struct of_irq oirq;
-	const u32 *opicprop;
-	unsigned int opicplen;
-	unsigned int virqs[16];
-
-	/* Check for obsolete "open-pic-interrupt" property. If present, then
-	 * map those interrupts using the default interrupt host and default
-	 * trigger
-	 */
-	opicprop = of_get_property(np, "open-pic-interrupt", &opicplen);
-	if (opicprop) {
-		opicplen /= sizeof(u32);
-		for (i = 0; i < opicplen; i++) {
-			if (count > 15)
-				break;
-			virqs[count] = irq_create_mapping(NULL, *(opicprop++));
-			if (virqs[count] == NO_IRQ)
-				printk(KERN_ERR "Unable to allocate interrupt "
-				       "number for %s\n", np->full_name);
-			else
-				count++;
-
-		}
-	}
-	/* Else use normal interrupt tree parsing */
-	else {
-		/* First try to do a proper OF tree parsing */
-		for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
-		     index++) {
-			if (count > 15)
-				break;
-			virqs[count] = irq_create_of_mapping(oirq.controller,
-							    oirq.specifier,
-							    oirq.size);
-			if (virqs[count] == NO_IRQ)
-				printk(KERN_ERR "Unable to allocate interrupt "
-				       "number for %s\n", np->full_name);
-			else
-				count++;
-		}
-	}
-
-	/* Now request them */
-	for (i = 0; i < count; i++) {
-		if (request_irq(virqs[i], handler, 0, name, NULL)) {
-			printk(KERN_ERR "Unable to request interrupt %d for "
-			       "%s\n", virqs[i], np->full_name);
-			return;
-		}
-	}
-}
-
 /*
  * Initialize handlers for the set of interrupts caused by hardware errors
  * and power system events.
@@ -138,14 +82,15 @@ static int __init init_ras_IRQ(void)
 	/* Internal Errors */
 	np = of_find_node_by_path("/event-sources/internal-errors");
 	if (np != NULL) {
-		request_ras_irqs(np, ras_error_interrupt, "RAS_ERROR");
+		request_event_sources_irqs(np, ras_error_interrupt,
+					   "RAS_ERROR");
 		of_node_put(np);
 	}
 
 	/* EPOW Events */
 	np = of_find_node_by_path("/event-sources/epow-events");
 	if (np != NULL) {
-		request_ras_irqs(np, ras_epow_interrupt, "RAS_EPOW");
+		request_event_sources_irqs(np, ras_epow_interrupt, "RAS_EPOW");
 		of_node_put(np);
 	}
 

^ permalink raw reply

* Re: [Patch 2/2] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: Paul Mackerras @ 2010-05-17 12:32 UTC (permalink / raw)
  To: K.Prasad
  Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
	Frederic Weisbecker, David Gibson, linuxppc-dev@ozlabs.org,
	Alan Stern, Roland McGrath
In-Reply-To: <20100514065530.GA6195@in.ibm.com>

On Fri, May 14, 2010 at 12:25:31PM +0530, K.Prasad wrote:

> Okay. I will re-use single_step_exception() after modifications; it
> appearsto have no in-kernel users for it.

It's called from exceptions-64s.S, head_32.S and head_8xx.S in
arch/powerpc/kernel.

> > Suppose the address at which the data breakpoint has been unmapped,
> > and the process has a handler for the SIGSEGV signal.  When we try to
> > single-step the load or store, we will get a DSI (0x300) interrupt,
> > call into do_page_fault, and end up sending the process a SIGSEGV.
> > That will invoke the signal handler, which can then do anything it
> > likes.  It can do a blocking system call, it can longjmp() back into
> > its main event, or it can return from the signal handler.  Only in the
> > last case will it retry the load or store, and then only if the signal
> > handler hasn't modified the NIP value in the signal frame.  That's
> > what I mean by "doesn't return to the instruction".
> > 
> 
> At the outset, this seemed to be a scary thing to happen; but turns out
> to be harmful only to the extent of generating a false hw-breakpoint
> exception in certain cases. A case-by-case basis analysis reveals thus:
> 
> Consider an instruction stream i1, i2, i3, ... iN, where i1 has
> finished execution and i2 is about to be executed but has generated a
> DSI interrupt with the above-mentioned conditions i.e. DSISR indicates a
> DABR match + Page-Table entry not found. Now according to do_hash_page
> in exception-64s.S (as pasted below), do_page_fault() and do_dabr() are
> invoked one after the other.
> 
> _STATIC(do_hash_page)
> 	std	r3,_DAR(r1)
> 	std	r4,_DSISR(r1)
> 
> 	andis.	r0,r4,0xa410		/* weird error? */
> 	bne-	handle_page_fault	/* if not, try to insert a HPTE */
> 	andis.  r0,r4,DSISR_DABRMATCH@h
> 	bne-    handle_dabr_fault

Note that bne is not a procedure call; we'll actually get two DSIs in
this scenario.  But I don't think that matters.  Also note that the
branch to handle_page_fault here is not for the HPTE-not-found case;
it's for the unusual errors.  So we'll handle the HPTE insertion after
handling the DABR match.

> Thus, when control returns to user-space to instruction 'i2', the
> hw_breakpoint_handler() has completed execution, and a SIGSEGV is pending
> to be delivered and single-stepping enabled MSR_SE is set. Upon return to
> user-space, the handler for SIGSEGV is executed and it may perform one of
> the following (as you stated previously):
> (a) Make a blocking syscall, eventually yielding the CPU to a new thread
> (b) Jump to a different instruction in user-space, say iN, and not complete
> the execution of instruction i2 at all.
> (c) Return to instruction i2 and complete the execution.
> 
> In case of (a), the context-switches should not affect the ability to
> single-step the instruction when the thread is eventually scheduled to
> run. The thread, when scheduled onto the CPU will complete signal
> handling, return to execute instruction i2, cause single-step exception,
> restore breakpoints and run smoothly thereafter.

Right.  However, the thread is running the signal handler without the
DABR being set, which is unfortunate.

> In case of (b), the new instruction iN is single-stepped, the breakpoint
> values are restored and the hw-breakpoint exception callback is invoked
> after iN is executed. The user of this breakpoint i.e. the caller of
> register_user_hw_breakpoint() who had placed a breakpoint on addressed
> accessed by instruction i2 will be confused to find that an unrelated
> instruction (which may not be a load/store) has caused the breakpoint.

That's the case if the signal handler modifies the NIP value in the
register set saved on the stack and returns.  If the signal handler
instead simply jumps to instruction iN (e.g. with longjmp or
siglongjmp), we'll never get the single-step callback.

> If so desired, we may adopt the 'trigger-before-execute' semantics for
> user-space breakpoints wherein the hw-breakpoint callback (through
> perf_bp_event()) is invoked in hw_breakpoint_handler() itself. This
> would indicate to the user that the impending instruction causes a DABR
> 'hit' but it may or may not be executed due to the role of
> signal-handler or due to self-modifying code (as mentioned below).
> 
> Kindly let me know what you think about it.
> 
> (c) is the normal execution path we desire. The instruction i2 will be
> safely single-stepped and breakpoints are restored.
> 
> > The instruction could be changed underneath us if the program is
> > multi-threaded and another thread writes another instruction to the
> > instruction word where the load or store is.  Or it could use mmap()
> > to map some other page at the address of the load or store.  Either
> > way we could end up with a different instruction there.
> > 
> 
> If the instruction that originally caused the DABR exception is changed,
> the new instruction in its place would still single-step to restore
> breakpoint values. However the user of breakpoint interface will be
> confused to find that the callback is invoked for an irrelevant
> instruction.
> 
> It could be circumvented, to an extent, through the use of
> trigger-before-execute semantics (as described before).

I don't think we want to do trigger-before-execute.  Ideally what we
want to ensure at all times is that either DABR is set (enabled) or
MSR.SE is set, but not both.  To ensure that we'd have to modify the
signal delivery code and possibly other places.

> > If we do get a context switch, e.g. as a result of a page fault, and
> > then switch back to the task, it looks to me like we will end up with
> > MSR_SE and DABR both set.  I don't suppose that will actually cause
> > any real problem besides double-counting the hit.
> > 
> 
> Page fault exception will be handled before hw_breakpoint_handler(),
> hence MSR_SE would not have been set if a context-switch happened in
> pange-fault handling itself. I don't see a case where both MSR_SE and
> DABR will be set together.

Imagine this scenario: we get the DABR match, set MSR_SE and return to
the task.  In the meantime another higher-priority task has become
runnable and our need_resched flag is set, so we call schedule() on
the way back out to usermode.  The other task runs and then blocks and
our task gets scheduled again.  As part of the context switch,
arch_install_hw_breakpoint() will get called and will set DABR.  So
we'll return to usermode with both DABR and MSE_SE set.

> Thanks for the comments. Let me know if the analysis above is incorrect
> or if I've failed to recognise any important issue that you pointed out.
> I will send out a patch with changes to emulate_single_step() in the
> next version of the patchset, if I don't hear any further comments.

We haven't discussed at all the case where the breakpoint is a per-cpu
breakpoint or where it's a per-task breakpoint but the DABR match
occurs within the kernel -- which can happen, even for a user address,
in __get_user, __put_user, __copy_tofrom_user, etc.  If the access
there is to a bad address, we'll invoke the exception case in
bad_page_fault(), which looks to be another place where we need to
recognize that single-stepping won't succeed and reinstall the DABR
setting.  Do we count that as an event or not? - I'm not sure.

Paul.

^ permalink raw reply

* [PATCH] powerpc/pseries: Add support for IO Event interrupt drivers
From: Mark Nelson @ 2010-05-17 12:53 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Tseng-hui Lin

This patch adds support for handling IO Event interrupts which come
through at the /event-sources/ibm,io-events device tree node.

There is one ibm,io-events interrupt, but this interrupt might be used
for multiple I/O devices, each with their own separate driver. So, we
create a platform interrupt handler that will do the RTAS check-exception
call and then call the appropriate driver's interrupt handler (the one(s)
that registered with a scope that matches the scope of the incoming
interrupt).

So, a driver for a device that uses IO Event interrupts will register
it's interrupt service routine (or interrupt handler) with the platform
code using ioei_register_isr(). This register function takes a function
pointer to the driver's handler and the scope that the driver is
interested in (scopes defined in arch/powerpc/include/asm/io_events.h).
The driver's handler must take a pointer to a struct io_events_section
and must not return anything.

The platform code registers io_event_interrupt() as the interrupt handler
for the ibm,io-events interrupt. Upon receiving an IO Event interrupt, it
checks the scope of the incoming interrupt and only calls those drivers'
handlers that have registered as being interested in that scope.

It is possible for a single driver to register the same function pointer
more than once with different scopes if it is interested in more than one
type of IO Event interrupt. If a handler wants to be notified of all
incoming IO Event interrupts it can register with IOEI_SCOPE_ANY.

A driver can unregister to stop receiving the IO Event interrupts using
ioei_unregister_isr(), passing it the same function pointer to the
driver's handler and the scope the driver was registered with.

Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
 arch/powerpc/include/asm/io_events.h       |   40 +++++
 arch/powerpc/platforms/pseries/Makefile    |    2 
 arch/powerpc/platforms/pseries/io_events.c |  205 +++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+), 1 deletion(-)

Index: upstream/arch/powerpc/include/asm/io_events.h
===================================================================
--- /dev/null
+++ upstream/arch/powerpc/include/asm/io_events.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010 IBM Corporation, Mark Nelson
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_POWERPC_IOEVENTS_H
+#define _ASM_POWERPC_IOEVENTS_H
+
+struct io_events_section {
+	u16	id;			// Unique section identifier	x00-x01
+	u16	length;			// Section length (bytes)	x02-x03
+	u8	version;		// Section Version		x04-x04
+	u8	sec_subtype;		// Section subtype		x05-x05
+	u16	creator_id;		// Creator Component ID		x06-x07
+	u8	event_type;		// IO-Event Type		x08-x08
+	u8	rpc_field_len;		// PRC Field Length		x09-x09
+	u8	scope;			// Error/Event Scope		x0A-x0A
+	u8	event_subtype;		// I/O-Event Sub-Type		x0B-x0B
+	u32	drc_index;		// DRC Index			x0C-x0F
+	u32	rpc_data[];		// RPC Data (optional)		x10-...
+};
+
+#define IOEI_SCOPE_NOT_APP	0x00
+#define IOEI_SCOPE_RIO_HUB	0x36
+#define IOEI_SCOPE_RIO_BRIDGE	0x37
+#define IOEI_SCOPE_PHB		0x38
+#define IOEI_SCOPE_EADS_GLOBAL	0x39
+#define IOEI_SCOPE_EADS_SLOT	0x3A
+#define IOEI_SCOPE_TORRENT_HUB	0x3B
+#define IOEI_SCOPE_SERVICE_PROC	0x51
+#define IOEI_SCOPE_ANY		-1
+
+int ioei_register_isr(void (*isr)(struct io_events_section *), int scope);
+int ioei_unregister_isr(void (*isr)(struct io_events_section *), int scope);
+
+#endif /* _ASM_POWERPC_IOEVENTS_H */
Index: upstream/arch/powerpc/platforms/pseries/io_events.c
===================================================================
--- /dev/null
+++ upstream/arch/powerpc/platforms/pseries/io_events.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2010 IBM Corporation, Mark Nelson
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#include <asm/io_events.h>
+#include <asm/rtas.h>
+#include <asm/irq.h>
+
+#include "event_sources.h"
+
+struct ioei_consumer {
+	void (*ioei_isr)(struct io_events_section *);
+	int scope;
+	struct ioei_consumer *next;
+};
+
+static int ioei_check_exception_token;
+
+static unsigned char ioei_log_buf[RTAS_ERROR_LOG_MAX];
+static DEFINE_SPINLOCK(ioei_log_buf_lock);
+
+static struct ioei_consumer *ioei_isr_list;
+static DEFINE_SPINLOCK(ioei_isr_list_lock);
+
+int ioei_register_isr(void (*isr)(struct io_events_section *), int scope)
+{
+	struct ioei_consumer *iter;
+	struct ioei_consumer *cons;
+	int ret = 0;
+
+	spin_lock(&ioei_isr_list_lock);
+	/* check to see if we've already registered this function with
+	 * this scope. If we have, don't register it again
+	 */
+	iter = ioei_isr_list;
+	while (iter) {
+		if (iter->ioei_isr == isr && iter->scope == scope)
+			break;
+		iter = iter->next;
+	}
+
+	if (iter) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	cons = kmalloc(sizeof(struct ioei_consumer), GFP_KERNEL);
+
+	if (!cons) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cons->ioei_isr = isr;
+	cons->scope = scope;
+
+	cons->next = ioei_isr_list;
+	ioei_isr_list = cons;
+
+out:
+	spin_unlock(&ioei_isr_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ioei_register_isr);
+
+int ioei_unregister_isr(void (*isr)(struct io_events_section *), int scope)
+{
+	struct ioei_consumer *iter;
+	struct ioei_consumer *prev = NULL;
+	int ret = 0;
+
+	spin_lock(&ioei_isr_list_lock);
+	iter = ioei_isr_list;
+	while (iter) {
+		if (iter->ioei_isr == isr && iter->scope == scope)
+			break;
+		prev = iter;
+		iter = iter->next;
+	}
+
+	if (!iter) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (prev)
+		prev->next = iter->next;
+	else
+		ioei_isr_list = iter->next;
+
+	kfree(iter);
+
+out:
+	spin_unlock(&ioei_isr_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ioei_unregister_isr);
+
+static void ioei_call_consumers(int scope, struct io_events_section *sec)
+{
+	struct ioei_consumer *iter;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioei_isr_list_lock, flags);
+	iter = ioei_isr_list;
+	while (iter) {
+		if (iter->scope == scope || iter->scope == IOEI_SCOPE_ANY)
+			iter->ioei_isr(sec);
+		iter = iter->next;
+	}
+
+	spin_unlock_irqrestore(&ioei_isr_list_lock, flags);
+}
+
+#define EXT_INT_VECTOR_OFFSET	0x500
+#define RTAS_TYPE_IO_EVENT	0xE1
+
+static irqreturn_t io_event_interrupt(int irq, void *dev_id)
+{
+	struct rtas_error_log *rtas_elog;
+	struct io_events_section *ioei_sec;
+	char *ch_ptr;
+	int status;
+	u16 *sec_len;
+
+	spin_lock(&ioei_log_buf_lock);
+
+	status = rtas_call(ioei_check_exception_token, 6, 1, NULL,
+			   EXT_INT_VECTOR_OFFSET,
+			   irq_map[irq].hwirq,
+			   RTAS_IO_EVENTS, 1 /*Time Critical */,
+			   __pa(&ioei_log_buf),
+				rtas_get_error_log_max());
+
+	rtas_elog = (struct rtas_error_log *)ioei_log_buf;
+
+	if (status != 0)
+		goto out;
+
+	/* We assume that we will only ever get called for io-event
+	 * interrupts. But if we get called with something else
+	 * make some noise about it.
+	 */
+	if (rtas_elog->type != RTAS_TYPE_IO_EVENT) {
+		pr_warning("IO Events: We got called with an event type of %d"
+			   " rather than %d!\n", rtas_elog->type,
+			   RTAS_TYPE_IO_EVENT);
+		WARN_ON(1);
+		goto out;
+	}
+
+	/* there are 24 bytes of event log data before the first section
+	 * (Main-A) begins
+	 */
+	ch_ptr = (char *)ioei_log_buf + 24;
+
+	/* loop through all the sections until we get to the IO Events
+	 * Section, with section ID "IE"
+	 */
+	while (*ch_ptr != 'I' && *(ch_ptr + 1) != 'E') {
+		sec_len = (u16 *)(ch_ptr + 2);
+		ch_ptr += *sec_len;
+	}
+
+	ioei_sec = (struct io_events_section *)ch_ptr;
+
+	ioei_call_consumers(ioei_sec->scope, ioei_sec);
+
+out:
+	spin_unlock(&ioei_log_buf_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int __init init_ioei_IRQ(void)
+{
+	struct device_node *np;
+
+	ioei_check_exception_token = rtas_token("check-exception");
+
+	np = of_find_node_by_path("/event-sources/ibm,io-events");
+	if (np != NULL) {
+		request_event_sources_irqs(np, io_event_interrupt, "IO_EVENT");
+		of_node_put(np);
+	}
+
+	return 0;
+}
+device_initcall(init_ioei_IRQ);
+
Index: upstream/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- upstream.orig/arch/powerpc/platforms/pseries/Makefile
+++ upstream/arch/powerpc/platforms/pseries/Makefile
@@ -8,7 +8,7 @@ endif
 
 obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o event_sources.o ras.o \
-			   firmware.o power.o dlpar.o
+			   firmware.o power.o dlpar.o io_events.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o

^ permalink raw reply

* Re: "event-scan failed" logflood
From: nello martuscielli @ 2010-05-17 12:58 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1273786104.21352.190.camel@pasglop>

Benjamin Herrenschmidt <benh <at> kernel.crashing.org> writes:

_omissis__
> 
> Ok, that gives us a good thing to use to not do the scanning then. If
> that's 0 then we assume it's a bogus OF and we disable the scan
> completely. I'll do a patch later today, though feel free to beat me to
> it.
> 
> Cheers,
> Ben.
> 

hi, is there available that patch?
With the fresh new 2.6.34 the logflood problem is still present.

thanks,
--nello

^ permalink raw reply

* Re: [PATCH v3 1/3] ptp: Added a brand new class driver for ptp clocks.
From: Wolfgang Grandegger @ 2010-05-17 15:41 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, devicetree-discuss, linuxppc-dev
In-Reply-To: <aa2a85799677c08001b152c2921d0e55d5693ffa.1273855017.git.richard.cochran@omicron.at>

On 05/14/2010 06:45 PM, Richard Cochran wrote:
> This patch adds an infrastructure for hardware clocks that implement
> IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a
> registration method to particular hardware clock drivers. Each clock is
> exposed to user space as a character device with ioctls that allow tuning
> of the PTP clock.
> 
> Signed-off-by: Richard Cochran <richard.cochran@omicron.at>

Tested-by: Wolfgang Grandegger <wg@denx.de>

on my Freescale MPC8313 setup with ptpd and ptpv2d.

Wolfgang.

^ permalink raw reply

* Re: [PATCH v3 3/3] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Wolfgang Grandegger @ 2010-05-17 15:41 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, devicetree-discuss, linuxppc-dev
In-Reply-To: <ee6c3edca3ee6aa86565e59da999375f79c9de1b.1273855017.git.richard.cochran@omicron.at>

On 05/14/2010 06:46 PM, Richard Cochran wrote:
> The eTSEC includes a PTP clock with quite a few features. This patch adds
> support for the basic clock adjustment functions, plus two external time
> stamps and one alarm.
> 
> Signed-off-by: Richard Cochran <richard.cochran@omicron.at>

Tested-by: Wolfgang Grandegger <wg@denx.de>

on my Freescale MPC8313 setup with ptpd and ptpv2d.

FYI: checkplatch.pl reports various errors for this patch series.

Wolfgang.

^ 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