Skip to contentSkip to conversation

cell patches for 2.6.25

PATCH In review [email protected] 2 participants 28 messages Dec 18, 2007 – Dec 19, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover cell patches for 2.6.25

These are the patches I have collected for 2.6.25. It's been a bit since the first call-for-patches for that version, but as it seems that 2.6.24 isn't imminent yet, I hope it's not too late for them.

Everyone, if there is some cell related patch that is not yet in powerpc.git, in cell-2.6.git#spufs or in this series, it probably fell under the table and you should resend it.

Paul, if there are no objections to these patches, please pull them from

git://git.kernel.org/pub/scm/linux/kernel/git/arnd/cell-2.6.git for-2.6.25

Thanks,

	Arnd <><

--

#1 lore raw

PATCH 1/18 perfmon2: make pm_interval register read/write

The pm_interval register in the Cell PMU is read/write, but was implemented in the kernel as write-only. Previously, the written value was saved in a "shadow" copy so calls to cbe_read_pm() could return the value.

Perfmon2 needs to be able to read the current values of pm_interval, so change cbe_read_pm() to read the actual register instead of the "shadow" copy. There is currently no code in the kernel that tries to read the pm_interval register with cbe_read_pm() (expecting to receive the "shadow" value), so this should not break any existing code.

---
 arch/powerpc/platforms/cell/pmu.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/powerpc/platforms/cell/pmu.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/pmu.c
===================================================================
@@ -213,7 +213,7 @@ u32 cbe_read_pm(u32 cpu, enum pm_reg_nam
 		break;
 
 	case pm_interval:
-		READ_SHADOW_REG(val, pm_interval);
+		READ_MMIO_UPPER32(val, pm_interval);
 		break;
 
 	case pm_start_stop:
#2 lore raw

PATCH 2/18 OProfile: fix cbe pm signal routing problem

In reply to [email protected]

Fix debug_bus_control and group_control PMU register values set up in set_pm_event(). Initialize variables before calling set_pm_event(). Delete unused static array and code that initialized it. Rename constant to better reflect usage.

---
 arch/powerpc/oprofile/op_model_cell.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)
arch/powerpc/oprofile/op_model_cell.c +11 -9
Index: linux-2.6-new/arch/powerpc/oprofile/op_model_cell.c
===================================================================
@@ -61,7 +61,7 @@ static unsigned int spu_cycle_reset;
 #define NUM_THREADS 2         /* number of physical threads in
 			       * physical processor
 			       */
-#define NUM_TRACE_BUS_WORDS 4
+#define NUM_DEBUG_BUS_WORDS 4
 #define NUM_INPUT_BUS_WORDS 2
 
 #define MAX_SPU_COUNT 0xFFFFFF	/* maximum 24 bit LFSR value */
@@ -169,7 +169,6 @@ static DEFINE_SPINLOCK(virt_cntr_lock);
 
 static u32 ctr_enabled;
 
-static unsigned char trace_bus[NUM_TRACE_BUS_WORDS];
 static unsigned char input_bus[NUM_INPUT_BUS_WORDS];
 
 /*
@@ -298,7 +297,7 @@ static void set_pm_event(u32 ctr, int ev
 
 	p->signal_group = event / 100;
 	p->bus_word = bus_word;
-	p->sub_unit = (unit_mask & 0x0000f000) >> 12;
+	p->sub_unit = GET_SUB_UNIT(unit_mask);
 
 	pm_regs.pm07_cntrl[ctr] = 0;
 	pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
@@ -334,16 +333,16 @@ static void set_pm_event(u32 ctr, int ev
 		p->bit = signal_bit;
 	}
 
-	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++) {
+	for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) {
 		if (bus_word & (1 << i)) {
 			pm_regs.debug_bus_control |=
-			    (bus_type << (31 - (2 * i) + 1));
+			    (bus_type << (30 - (2 * i)));
 
 			for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) {
 				if (input_bus[j] == 0xff) {
 					input_bus[j] = i;
 					pm_regs.group_control |=
-					    (i << (31 - i));
+					    (i << (30 - (2 * j)));
 
 					break;
 				}
@@ -450,6 +449,12 @@ static void cell_virtual_cntr(unsigned l
 	hdw_thread = 1 ^ hdw_thread;
 	next_hdw_thread = hdw_thread;
 
+	pm_regs.group_control = 0;
+	pm_regs.debug_bus_control = 0;
+
+	for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
+		input_bus[i] = 0xff;
+
 	/*
 	 * There are some per thread events.  Must do the
 	 * set event, for the thread that is being started
@@ -619,9 +624,6 @@ static int cell_reg_setup(struct op_coun
 		pmc_cntrl[1][i].vcntr = i;
 	}
 
-	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++)
-		trace_bus[i] = 0xff;
-
 	for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
 		input_bus[i] = 0xff;
 
#3 lore raw

PATCH 3/18 cell: add missing \n

In reply to [email protected]

Two printk() calls were missing the terminating '\n'.

---
 arch/powerpc/platforms/cell/spu_manage.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/platforms/cell/spu_manage.c +2 -2
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_manage.c
===================================================================
@@ -345,7 +345,7 @@ static int __init of_create_spu(struct s
 		}
 		ret = spu_map_interrupts_old(spu, spe);
 		if (ret) {
-			printk(KERN_ERR "%s: could not map interrupts",
+			printk(KERN_ERR "%s: could not map interrupts\n",
 				spu->name);
 			goto out_unmap;
 		}
@@ -525,7 +525,7 @@ static int __init init_affinity(void)
 		if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
 			init_affinity_qs20_harcoded();
 		else
-			printk("No affinity configuration found");
+			printk("No affinity configuration found\n");
 	}
 
 	return 0;
#4 lore raw

PATCH 4/18 Set archdata.dma_data for direct DMA in cell_dma_dev_setup()

In reply to [email protected]

Store a pointer to the direct_dma_offset in each device's dma_data in the case where we're using the direct DMA ops.

---
 arch/powerpc/platforms/cell/iommu.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/powerpc/platforms/cell/iommu.c +3 -2
Index: linux-2.6-new/arch/powerpc/platforms/cell/iommu.c
===================================================================
@@ -496,9 +496,10 @@ static void cell_dma_dev_setup(struct de
 	struct cbe_iommu *iommu;
 	struct dev_archdata *archdata = &dev->archdata;
 
-	/* If we run without iommu, no need to do anything */
-	if (get_pci_dma_ops() == &dma_direct_ops)
+	if (get_pci_dma_ops() == &dma_direct_ops) {
+		archdata->dma_data = &dma_direct_offset;
 		return;
+	}
 
 	/* Current implementation uses the first window available in that
 	 * node's iommu. We -might- do something smarter later though it may
#5 lore raw

Re: [POWERPC 04/18] Set archdata.dma_data for direct DMA in cell_dma_dev_setup()

Quoted 7 lines · On Tue, 2007-12-18 at 18:48 +0100, [email protected] wrote:

plain text document attachment (0014-Set-archdata.dma_data-for-direct-DMA-in-cell_dma_dev.patch) Store a pointer to the direct_dma_offset in each device's dma_data in the case where we're using the direct DMA ops.

Ack.

Quoted 22 lines
---
 arch/powerpc/platforms/cell/iommu.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

Index: linux-2.6-new/arch/powerpc/platforms/cell/iommu.c
===================================================================

arch/powerpc/platforms/cell/iommu.c +3 -2
@@ -496,9 +496,10 @@ static void cell_dma_dev_setup(struct de
 	struct cbe_iommu *iommu;
 	struct dev_archdata *archdata = &dev->archdata;
 
-	/* If we run without iommu, no need to do anything */
-	if (get_pci_dma_ops() == &dma_direct_ops)
+	if (get_pci_dma_ops() == &dma_direct_ops) {
+		archdata->dma_data = &dma_direct_offset;
 		return;
+	}
 
 	/* Current implementation uses the first window available in that
 	 * node's iommu. We -might- do something smarter later though it may
#6 lore raw

PATCH 5/18 Add celleb_dma_dev_setup()

In reply to [email protected]

Celleb always uses dma_direct_ops, and sets dma_direct_offset, so it too should set dma_data to dma_direct_offset.

Currently there's no pci_dma_dev_setup() routine for Celleb so add one.

---
 arch/powerpc/platforms/celleb/iommu.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)
arch/powerpc/platforms/celleb/iommu.c +13 -1
Index: linux-2.6-new/arch/powerpc/platforms/celleb/iommu.c
===================================================================
@@ -72,6 +72,17 @@ static void __init celleb_init_direct_ma
 	dma_direct_offset = dma_base;
 }
 
+static void celleb_dma_dev_setup(struct device *dev)
+{
+	dev->archdata.dma_ops = get_pci_dma_ops();
+	dev->archdata.dma_data = &dma_direct_offset;
+}
+
+static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	celleb_dma_dev_setup(&pdev->dev);
+}
+
 static int celleb_of_bus_notify(struct notifier_block *nb,
 				unsigned long action, void *data)
 {
@@ -81,7 +92,7 @@ static int celleb_of_bus_notify(struct n
 	if (action != BUS_NOTIFY_ADD_DEVICE)
 		return 0;
 
-	dev->archdata.dma_ops = get_pci_dma_ops();
+	celleb_dma_dev_setup(dev);
 
 	return 0;
 }
@@ -97,6 +108,7 @@ static int __init celleb_init_iommu(void
 
 	celleb_init_direct_mapping();
 	set_pci_dma_ops(&dma_direct_ops);
+	ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
 	bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
 
 	return 0;
#7 lore raw

Re: [POWERPC 05/18] Add celleb_dma_dev_setup()

Quoted 9 lines · On Tue, 2007-12-18 at 18:48 +0100, [email protected] wrote:

plain text document attachment (0015-Add-celleb_dma_dev_setup.patch) Celleb always uses dma_direct_ops, and sets dma_direct_offset, so it too should set dma_data to dma_direct_offset.

Currently there's no pci_dma_dev_setup() routine for Celleb so add one.

---

Ack.

Quoted 43 lines
 arch/powerpc/platforms/celleb/iommu.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

Index: linux-2.6-new/arch/powerpc/platforms/celleb/iommu.c
===================================================================

arch/powerpc/platforms/celleb/iommu.c +13 -1
@@ -72,6 +72,17 @@ static void __init celleb_init_direct_ma
 	dma_direct_offset = dma_base;
 }
 
+static void celleb_dma_dev_setup(struct device *dev)
+{
+	dev->archdata.dma_ops = get_pci_dma_ops();
+	dev->archdata.dma_data = &dma_direct_offset;
+}
+
+static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	celleb_dma_dev_setup(&pdev->dev);
+}
+
 static int celleb_of_bus_notify(struct notifier_block *nb,
 				unsigned long action, void *data)
 {
@@ -81,7 +92,7 @@ static int celleb_of_bus_notify(struct n
 	if (action != BUS_NOTIFY_ADD_DEVICE)
 		return 0;
 
-	dev->archdata.dma_ops = get_pci_dma_ops();
+	celleb_dma_dev_setup(dev);
 
 	return 0;
 }
@@ -97,6 +108,7 @@ static int __init celleb_init_iommu(void
 
 	celleb_init_direct_mapping();
 	set_pci_dma_ops(&dma_direct_ops);
+	ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
 	bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
 
 	return 0;
#8 lore raw

PATCH 6/18 Use archdata.dma_data in dma_direct_ops

In reply to [email protected]

Now that all platforms using dma_direct_offset setup the archdata.dma_data correctly, we can change the dma_direct_ops to retrieve the offset from the dma_data, rather than directly from the global.

---
 arch/powerpc/kernel/dma_64.c |   18 +++++++++++++++---
 1 files changed, 15 insertions(+), 3 deletions(-)
arch/powerpc/kernel/dma_64.c +15 -3
Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================
@@ -117,6 +117,18 @@ EXPORT_SYMBOL(dma_iommu_ops);
  */
 unsigned long dma_direct_offset;
 
+static unsigned long get_dma_direct_offset(struct device *dev)
+{
+	unsigned long *offset;
+
+	offset = dev->archdata.dma_data;
+
+	if (offset)
+		return *offset;
+
+	return 0;
+}
+
 static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag)
 {
@@ -130,7 +142,7 @@ static void *dma_direct_alloc_coherent(s
 		return NULL;
 	ret = page_address(page);
 	memset(ret, 0, size);
-	*dma_handle = virt_to_abs(ret) | dma_direct_offset;
+	*dma_handle = virt_to_abs(ret) | get_dma_direct_offset(dev);
 
 	return ret;
 }
@@ -145,7 +157,7 @@ static dma_addr_t dma_direct_map_single(
 					size_t size,
 					enum dma_data_direction direction)
 {
-	return virt_to_abs(ptr) | dma_direct_offset;
+	return virt_to_abs(ptr) | get_dma_direct_offset(dev);
 }
 
 static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
@@ -161,7 +173,7 @@ static int dma_direct_map_sg(struct devi
 	int i;
 
 	for_each_sg(sgl, sg, nents, i) {
-		sg->dma_address = sg_phys(sg) | dma_direct_offset;
+		sg->dma_address = sg_phys(sg) | get_dma_direct_offset(dev);
 		sg->dma_length = sg->length;
 	}
 
#9 lore raw

Re: [POWERPC 06/18] Use archdata.dma_data in dma_direct_ops

Quoted 8 lines · On Tue, 2007-12-18 at 18:48 +0100, [email protected] wrote:

plain text document attachment (0016-Use-archdata.dma_data-in-dma_direct_ops.patch)
Now that all platforms using dma_direct_offset setup the archdata.dma_data correctly, we can change the dma_direct_ops to retrieve the offset from the dma_data, rather than directly from the global.

Ack.

Quoted 54 lines
 arch/powerpc/kernel/dma_64.c |   18 +++++++++++++++---
 1 files changed, 15 insertions(+), 3 deletions(-)

Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================

arch/powerpc/kernel/dma_64.c +15 -3
@@ -117,6 +117,18 @@ EXPORT_SYMBOL(dma_iommu_ops);
  */
 unsigned long dma_direct_offset;
 
+static unsigned long get_dma_direct_offset(struct device *dev)
+{
+	unsigned long *offset;
+
+	offset = dev->archdata.dma_data;
+
+	if (offset)
+		return *offset;
+
+	return 0;
+}
+
 static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag)
 {
@@ -130,7 +142,7 @@ static void *dma_direct_alloc_coherent(s
 		return NULL;
 	ret = page_address(page);
 	memset(ret, 0, size);
-	*dma_handle = virt_to_abs(ret) | dma_direct_offset;
+	*dma_handle = virt_to_abs(ret) | get_dma_direct_offset(dev);
 
 	return ret;
 }
@@ -145,7 +157,7 @@ static dma_addr_t dma_direct_map_single(
 					size_t size,
 					enum dma_data_direction direction)
 {
-	return virt_to_abs(ptr) | dma_direct_offset;
+	return virt_to_abs(ptr) | get_dma_direct_offset(dev);
 }
 
 static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
@@ -161,7 +173,7 @@ static int dma_direct_map_sg(struct devi
 	int i;
 
 	for_each_sg(sgl, sg, nents, i) {
-		sg->dma_address = sg_phys(sg) | dma_direct_offset;
+		sg->dma_address = sg_phys(sg) | get_dma_direct_offset(dev);
 		sg->dma_length = sg->length;
 	}
 
#10 lore raw

PATCH 7/18 Have cell use its own dma_direct_offset variable

In reply to [email protected]

Rather than using the global variable, have cell use its own variable to store the direct DMA offset.

---
 arch/powerpc/platforms/cell/iommu.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)
arch/powerpc/platforms/cell/iommu.c +6 -4
Index: linux-2.6-new/arch/powerpc/platforms/cell/iommu.c
===================================================================
@@ -490,6 +490,8 @@ static struct cbe_iommu *cell_iommu_for_
 	return NULL;
 }
 
+static unsigned long cell_dma_direct_offset;
+
 static void cell_dma_dev_setup(struct device *dev)
 {
 	struct iommu_window *window;
@@ -497,7 +499,7 @@ static void cell_dma_dev_setup(struct de
 	struct dev_archdata *archdata = &dev->archdata;
 
 	if (get_pci_dma_ops() == &dma_direct_ops) {
-		archdata->dma_data = &dma_direct_offset;
+		archdata->dma_data = &cell_dma_direct_offset;
 		return;
 	}
 
@@ -655,7 +657,7 @@ static int __init cell_iommu_init_disabl
 
 	/* If we have no Axon, we set up the spider DMA magic offset */
 	if (of_find_node_by_name(NULL, "axon") == NULL)
-		dma_direct_offset = SPIDER_DMA_OFFSET;
+		cell_dma_direct_offset = SPIDER_DMA_OFFSET;
 
 	/* Now we need to check to see where the memory is mapped
 	 * in PCI space. We assume that all busses use the same dma
@@ -689,10 +691,10 @@ static int __init cell_iommu_init_disabl
 		return -ENODEV;
 	}
 
-	dma_direct_offset += base;
+	cell_dma_direct_offset += base;
 
 	printk("iommu: disabled, direct DMA offset is 0x%lx\n",
-	       dma_direct_offset);
+	       cell_dma_direct_offset);
 
 	return 0;
 }
#11 lore raw

Re: [POWERPC 07/18] Have cell use its own dma_direct_offset variable

Quoted 8 lines · On Tue, 2007-12-18 at 18:48 +0100, [email protected] wrote:

plain text document attachment (0017-Have-cell-use-its-own-dma_direct_offset-variable.patch) Rather than using the global variable, have cell use its own variable to store the direct DMA offset.

---

Ack.

Quoted 48 lines
 arch/powerpc/platforms/cell/iommu.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

Index: linux-2.6-new/arch/powerpc/platforms/cell/iommu.c
===================================================================

arch/powerpc/platforms/cell/iommu.c +6 -4
@@ -490,6 +490,8 @@ static struct cbe_iommu *cell_iommu_for_
 	return NULL;
 }
 
+static unsigned long cell_dma_direct_offset;
+
 static void cell_dma_dev_setup(struct device *dev)
 {
 	struct iommu_window *window;
@@ -497,7 +499,7 @@ static void cell_dma_dev_setup(struct de
 	struct dev_archdata *archdata = &dev->archdata;
 
 	if (get_pci_dma_ops() == &dma_direct_ops) {
-		archdata->dma_data = &dma_direct_offset;
+		archdata->dma_data = &cell_dma_direct_offset;
 		return;
 	}
 
@@ -655,7 +657,7 @@ static int __init cell_iommu_init_disabl
 
 	/* If we have no Axon, we set up the spider DMA magic offset */
 	if (of_find_node_by_name(NULL, "axon") == NULL)
-		dma_direct_offset = SPIDER_DMA_OFFSET;
+		cell_dma_direct_offset = SPIDER_DMA_OFFSET;
 
 	/* Now we need to check to see where the memory is mapped
 	 * in PCI space. We assume that all busses use the same dma
@@ -689,10 +691,10 @@ static int __init cell_iommu_init_disabl
 		return -ENODEV;
 	}
 
-	dma_direct_offset += base;
+	cell_dma_direct_offset += base;
 
 	printk("iommu: disabled, direct DMA offset is 0x%lx\n",
-	       dma_direct_offset);
+	       cell_dma_direct_offset);
 
 	return 0;
 }
#12 lore raw

PATCH 8/18 Have celleb use its own dma_direct_offset variable

In reply to [email protected]

Rather than using the global variable, have celleb use its own variable to store the direct DMA offset.

---
 arch/powerpc/platforms/celleb/iommu.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/platforms/celleb/iommu.c +4 -2
Index: linux-2.6-new/arch/powerpc/platforms/celleb/iommu.c
===================================================================
@@ -52,6 +52,8 @@ static int __init find_dma_window(u64 *i
 	return 0;
 }
 
+static unsigned long celleb_dma_direct_offset;
+
 static void __init celleb_init_direct_mapping(void)
 {
 	u64 lpar_addr, io_addr;
@@ -69,13 +71,13 @@ static void __init celleb_init_direct_ma
 				     ioid, DMA_FLAGS);
 	}
 
-	dma_direct_offset = dma_base;
+	celleb_dma_direct_offset = dma_base;
 }
 
 static void celleb_dma_dev_setup(struct device *dev)
 {
 	dev->archdata.dma_ops = get_pci_dma_ops();
-	dev->archdata.dma_data = &dma_direct_offset;
+	dev->archdata.dma_data = &celleb_dma_direct_offset;
 }
 
 static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
#13 lore raw

Re: [POWERPC 08/18] Have celleb use its own dma_direct_offset variable

Quoted 8 lines · On Tue, 2007-12-18 at 18:49 +0100, [email protected] wrote:

plain text document attachment (0018-Have-celleb-use-its-own-dma_direct_offset-variable.patch) Rather than using the global variable, have celleb use its own variable to store the direct DMA offset.

---

Ack.

Quoted 33 lines
 arch/powerpc/platforms/celleb/iommu.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

Index: linux-2.6-new/arch/powerpc/platforms/celleb/iommu.c
===================================================================

arch/powerpc/platforms/celleb/iommu.c +4 -2
@@ -52,6 +52,8 @@ static int __init find_dma_window(u64 *i
 	return 0;
 }
 
+static unsigned long celleb_dma_direct_offset;
+
 static void __init celleb_init_direct_mapping(void)
 {
 	u64 lpar_addr, io_addr;
@@ -69,13 +71,13 @@ static void __init celleb_init_direct_ma
 				     ioid, DMA_FLAGS);
 	}
 
-	dma_direct_offset = dma_base;
+	celleb_dma_direct_offset = dma_base;
 }
 
 static void celleb_dma_dev_setup(struct device *dev)
 {
 	dev->archdata.dma_ops = get_pci_dma_ops();
-	dev->archdata.dma_data = &dma_direct_offset;
+	dev->archdata.dma_data = &celleb_dma_direct_offset;
 }
 
 static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
#14 lore raw

PATCH 9/18 Remove the global dma_direct_offset

In reply to [email protected]

We no longer need the global dma_direct_offset, update the comment to reflect the new reality.

---
 arch/powerpc/kernel/dma_64.c      |    7 ++++---
 include/asm-powerpc/dma-mapping.h |    2 --
 2 files changed, 4 insertions(+), 5 deletions(-)
arch/powerpc/kernel/dma_64.c +4 -3
Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================
@@ -112,10 +112,11 @@ EXPORT_SYMBOL(dma_iommu_ops);
 /*
  * Generic direct DMA implementation
  *
- * This implementation supports a global offset that can be applied if
- * the address at which memory is visible to devices is not 0.
+ * This implementation supports a per-device offset that can be applied if
+ * the address at which memory is visible to devices is not 0. Platform code
+ * can point archdata.dma_data at an unsigned long holding the offset. By
+ * default no offset is used.
  */
-unsigned long dma_direct_offset;
 
 static unsigned long get_dma_direct_offset(struct device *dev)
 {
include/asm-powerpc/dma-mapping.h +0 -2
Index: linux-2.6-new/include/asm-powerpc/dma-mapping.h
===================================================================
@@ -186,8 +186,6 @@ static inline void dma_unmap_sg(struct d
 extern struct dma_mapping_ops dma_iommu_ops;
 extern struct dma_mapping_ops dma_direct_ops;
 
-extern unsigned long dma_direct_offset;
-
 #else /* CONFIG_PPC64 */
 
 #define dma_supported(dev, mask)	(1)
#15 lore raw

Re: [POWERPC 09/18] Remove the global dma_direct_offset

Quoted 8 lines · On Tue, 2007-12-18 at 18:49 +0100, [email protected] wrote:

plain text document attachment (0019-Remove-the-global-dma_direct_offset.patch)
We no longer need the global dma_direct_offset, update the comment to reflect the new reality.

---

Ack.

Quoted 37 lines
 arch/powerpc/kernel/dma_64.c      |    7 ++++---
 include/asm-powerpc/dma-mapping.h |    2 --
 2 files changed, 4 insertions(+), 5 deletions(-)

Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================

arch/powerpc/kernel/dma_64.c +4 -3
@@ -112,10 +112,11 @@ EXPORT_SYMBOL(dma_iommu_ops);
 /*
  * Generic direct DMA implementation
  *
- * This implementation supports a global offset that can be applied if
- * the address at which memory is visible to devices is not 0.
+ * This implementation supports a per-device offset that can be applied if
+ * the address at which memory is visible to devices is not 0. Platform code
+ * can point archdata.dma_data at an unsigned long holding the offset. By
+ * default no offset is used.
  */
-unsigned long dma_direct_offset;
 
 static unsigned long get_dma_direct_offset(struct device *dev)
 {

Index: linux-2.6-new/include/asm-powerpc/dma-mapping.h
===================================================================

include/asm-powerpc/dma-mapping.h +0 -2
@@ -186,8 +186,6 @@ static inline void dma_unmap_sg(struct d
 extern struct dma_mapping_ops dma_iommu_ops;
 extern struct dma_mapping_ops dma_direct_ops;
 
-extern unsigned long dma_direct_offset;
-
 #else /* CONFIG_PPC64 */
 
 #define dma_supported(dev, mask)	(1)
#16 lore raw

PATCH 10/18 Remove bogus comment in dma_direct_alloc_coherent()

In reply to [email protected]

Since commit c80d9133e99de1af607314107910a2a1645efb17 (Make direct DMA use node local allocations) went in this comment makes no sense.

---
 arch/powerpc/kernel/dma_64.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
arch/powerpc/kernel/dma_64.c +0 -1
Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================
@@ -137,7 +137,6 @@ static void *dma_direct_alloc_coherent(s
 	void *ret;
 	int node = dev->archdata.numa_node;
 
-	/* TODO: Maybe use the numa node here too ? */
 	page = alloc_pages_node(node, flag, get_order(size));
 	if (page == NULL)
 		return NULL;
#17 lore raw

Re: [POWERPC 10/18] Remove bogus comment in dma_direct_alloc_coherent()

Quoted 8 lines · On Tue, 2007-12-18 at 18:49 +0100, [email protected] wrote:

plain text document attachment (0020-Remove-bogus-comment-in-dma_direct_alloc_coherent.patch) Since commit c80d9133e99de1af607314107910a2a1645efb17 (Make direct DMA use node local allocations) went in this comment makes no sense.

---

Ack.

Quoted 16 lines
 arch/powerpc/kernel/dma_64.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

Index: linux-2.6-new/arch/powerpc/kernel/dma_64.c
===================================================================

arch/powerpc/kernel/dma_64.c +0 -1
@@ -137,7 +137,6 @@ static void *dma_direct_alloc_coherent(s
 	void *ret;
 	int node = dev->archdata.numa_node;
 
-	/* TODO: Maybe use the numa node here too ? */
 	page = alloc_pages_node(node, flag, get_order(size));
 	if (page == NULL)
 		return NULL;
#18 lore raw

PATCH 11/18 cell: Convert #include of asm/of_{platform, device}.h into linux/of_{platform, device}.h.

In reply to [email protected]
---
 arch/powerpc/platforms/cell/cbe_cpufreq.c     |    3 ++-
 arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c |    3 ++-
 arch/powerpc/platforms/cell/cbe_regs.c        |    4 ++--
 arch/powerpc/platforms/cell/iommu.c           |    2 +-
 arch/powerpc/platforms/cell/setup.c           |    2 +-
 arch/powerpc/platforms/celleb/iommu.c         |    3 +--
 arch/powerpc/platforms/celleb/setup.c         |    2 +-
 7 files changed, 10 insertions(+), 9 deletions(-)
arch/powerpc/platforms/cell/cbe_cpufreq.c +2 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -21,8 +21,9 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+
 #include <asm/machdep.h>
-#include <asm/of_platform.h>
 #include <asm/prom.h>
 #include <asm/cell-regs.h>
 #include "cbe_cpufreq.h"
arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c +2 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
===================================================================
@@ -23,7 +23,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <asm/of_platform.h>
+#include <linux/of_platform.h>
+
 #include <asm/processor.h>
 #include <asm/prom.h>
 #include <asm/pmi.h>
arch/powerpc/platforms/cell/cbe_regs.c +2 -2
Index: linux-2.6-new/arch/powerpc/platforms/cell/cbe_regs.c
===================================================================
@@ -9,13 +9,13 @@
 #include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 /*
arch/powerpc/platforms/cell/iommu.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/iommu.c
===================================================================
@@ -26,13 +26,13 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
+#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/udbg.h>
-#include <asm/of_platform.h>
 #include <asm/lmb.h>
 #include <asm/firmware.h>
 #include <asm/cell-regs.h>
arch/powerpc/platforms/cell/setup.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/setup.c
===================================================================
@@ -30,6 +30,7 @@
 #include <linux/console.h>
 #include <linux/mutex.h>
 #include <linux/memory_hotplug.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -51,7 +52,6 @@
 #include <asm/spu_priv1.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
arch/powerpc/platforms/celleb/iommu.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/celleb/iommu.c
===================================================================
@@ -22,8 +22,8 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
 #include <asm/firmware.h>
 
 #include "beat_wrapper.h"
arch/powerpc/platforms/celleb/setup.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/celleb/setup.c
===================================================================
@@ -40,6 +40,7 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/console.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -52,7 +53,6 @@
 #include <asm/time.h>
 #include <asm/spu_priv1.h>
 #include <asm/firmware.h>
-#include <asm/of_platform.h>
 #include <asm/rtas.h>
 #include <asm/cell-regs.h>
 
#19 lore raw

PATCH 12/18 cell: export force_sig_info()

In reply to [email protected]

Export force_sig_info to allow signals to be sent from a modular spufs.

---
 arch/powerpc/platforms/cell/spu_base.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +7 -0
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -47,6 +47,13 @@ struct cbe_spu_info cbe_spu_info[MAX_NUM
 EXPORT_SYMBOL_GPL(cbe_spu_info);
 
 /*
+ * The spufs fault-handling code needs to call force_sig_info to raise signals
+ * on DMA errors. Export it here to avoid general kernel-wide access to this
+ * function
+ */
+EXPORT_SYMBOL_GPL(force_sig_info);
+
+/*
  * Protects cbe_spu_info and spu->number.
  */
 static DEFINE_SPINLOCK(spu_lock);
#20 lore raw

PATCH 13/18 cell: safer of_has_vicinity routine

In reply to [email protected]

This patch changes the way we check for the existence of vicinity property in spe device nodes.

The new implementation does not depend on having an initialized cbe_spu_info[0].spus, and checks for presence of vicinity in all nodes, not only in the first one.

---
 arch/powerpc/platforms/cell/spu_manage.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)
arch/powerpc/platforms/cell/spu_manage.c +8 -3
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_manage.c
===================================================================
@@ -422,10 +422,15 @@ static void init_affinity_qs20_harcoded(
 
 static int of_has_vicinity(void)
 {
-	struct spu* spu;
+	struct device_node *dn;
 
-	spu = list_first_entry(&cbe_spu_info[0].spus, struct spu, cbe_list);
-	return of_find_property(spu_devnode(spu), "vicinity", NULL) != NULL;
+	for_each_node_by_type(dn, "spe") {
+		if (of_find_property(dn, "vicinity", NULL))  {
+			of_node_put(dn);
+			return 1;
+		}
+	}
+	return 0;
 }
 
 static struct spu *devnode_spu(int cbe, struct device_node *dn)
#21 lore raw

PATCH 14/18 cell: handle kernel SLB setup in spu_base.c

In reply to [email protected]

Currently, the SPU context switch code (spufs/switch.c) sets up the SPU's SLBs directly, which requires some low-level mm stuff.

This change moves the kernel SLB setup to spu_base.c, by exposing a function spu_setup_kernel_slbs() to do this setup. This allows us to remove the low-level mm code from switch.c, making it possible to later move switch.c to the spufs module.

Also, add a struct spu_slb for the cases where we need to deal with SLB entries.

---
 arch/powerpc/platforms/cell/spu_base.c     |   49 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/cell/spufs/switch.c |   33 +------------------
 include/asm-powerpc/spu.h                  |    4 ++
 3 files changed, 54 insertions(+), 32 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +49 -0
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -34,6 +34,7 @@
 #include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
+#include <asm/spu_csa.h>
 #include <asm/xmon.h>
 #include <asm/prom.h>
 
@@ -73,6 +74,10 @@ static LIST_HEAD(spu_full_list);
 static DEFINE_SPINLOCK(spu_full_list_lock);
 static DEFINE_MUTEX(spu_full_list_mutex);
 
+struct spu_slb {
+	u64 esid, vsid;
+};
+
 void spu_invalidate_slbs(struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -150,6 +155,18 @@ static void spu_restart_dma(struct spu *
 		out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
 }
 
+static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
+{
+	struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+	pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
+			__func__, slbe, slb->vsid, slb->esid);
+
+	out_be64(&priv2->slb_index_W, slbe);
+	out_be64(&priv2->slb_vsid_RW, slb->vsid);
+	out_be64(&priv2->slb_esid_RW, slb->esid);
+}
+
 static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -239,6 +256,38 @@ static int __spu_trap_data_map(struct sp
 	return 0;
 }
 
+static void __spu_kernel_slb(void *addr, struct spu_slb *slb)
+{
+	unsigned long ea = (unsigned long)addr;
+	u64 llp;
+
+	if (REGION_ID(ea) == KERNEL_REGION_ID)
+		llp = mmu_psize_defs[mmu_linear_psize].sllp;
+	else
+		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+
+	slb->vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
+		SLB_VSID_KERNEL | llp;
+	slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
+}
+
+/**
+ * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
+ * need to map both the context save area, and the save/restore code.
+ */
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, void *code)
+{
+	struct spu_slb code_slb, lscsa_slb;
+
+	__spu_kernel_slb(lscsa, &lscsa_slb);
+	__spu_kernel_slb(code, &code_slb);
+
+	spu_load_slb(spu, 0, &lscsa_slb);
+	if (lscsa_slb.esid != code_slb.esid)
+		spu_load_slb(spu, 1, &code_slb);
+}
+EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
+
 static irqreturn_t
 spu_irq_class_0(int irq, void *data)
 {
arch/powerpc/platforms/cell/spufs/switch.c +1 -32
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/switch.c
===================================================================
@@ -691,35 +691,8 @@ static inline void resume_mfc_queue(stru
 	out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void get_kernel_slb(u64 ea, u64 slb[2])
-{
-	u64 llp;
-
-	if (REGION_ID(ea) == KERNEL_REGION_ID)
-		llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	else
-		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
-	slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-		SLB_VSID_KERNEL | llp;
-	slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
-}
-
-static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
-{
-	struct spu_priv2 __iomem *priv2 = spu->priv2;
-
-	out_be64(&priv2->slb_index_W, slbe);
-	eieio();
-	out_be64(&priv2->slb_vsid_RW, slb[0]);
-	out_be64(&priv2->slb_esid_RW, slb[1]);
-	eieio();
-}
-
 static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
 {
-	u64 code_slb[2];
-	u64 lscsa_slb[2];
-
 	/* Save, Step 47:
 	 * Restore, Step 30.
 	 *     If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
@@ -735,11 +708,7 @@ static inline void setup_mfc_slbs(struct
 	 *     translation is desired by OS environment).
 	 */
 	spu_invalidate_slbs(spu);
-	get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
-	get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
-	load_mfc_slb(spu, code_slb, 0);
-	if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
-		load_mfc_slb(spu, lscsa_slb, 1);
+	spu_setup_kernel_slbs(spu, csa->lscsa, &spu_save_code);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
include/asm-powerpc/spu.h +4 -0
Index: linux-2.6-new/include/asm-powerpc/spu.h
===================================================================
@@ -104,6 +104,7 @@
 
 struct spu_context;
 struct spu_runqueue;
+struct spu_lscsa;
 struct device_node;
 
 enum spu_utilization_state {
@@ -200,6 +201,9 @@ int spu_irq_class_0_bottom(struct spu *s
 int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
+void spu_setup_kernel_slbs(struct spu *spu,
+		struct spu_lscsa *lscsa, void *code);
+
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);
 #else
#22 lore raw

PATCH 15/18 cell: use spu_load_slb for SLB setup

In reply to [email protected]

Now that we have a helper function to setup a SPU SLB, use it for __spu_trap_data_seq.

---
 arch/powerpc/platforms/cell/spu_base.c |   23 ++++++++++-------------
 1 files changed, 10 insertions(+), 13 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +10 -13
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -169,9 +169,8 @@ static inline void spu_load_slb(struct s
 
 static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 {
-	struct spu_priv2 __iomem *priv2 = spu->priv2;
 	struct mm_struct *mm = spu->mm;
-	u64 esid, vsid, llp;
+	struct spu_slb slb;
 	int psize;
 
 	pr_debug("%s\n", __FUNCTION__);
@@ -183,7 +182,7 @@ static int __spu_trap_data_seg(struct sp
 		printk("%s: invalid access during switch!\n", __func__);
 		return 1;
 	}
-	esid = (ea & ESID_MASK) | SLB_ESID_V;
+	slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
 
 	switch(REGION_ID(ea)) {
 	case USER_REGION_ID:
@@ -192,21 +191,21 @@ static int __spu_trap_data_seg(struct sp
 #else
 		psize = mm->context.user_psize;
 #endif
-		vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-				SLB_VSID_USER;
+		slb.vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_USER;
 		break;
 	case VMALLOC_REGION_ID:
 		if (ea < VMALLOC_END)
 			psize = mmu_vmalloc_psize;
 		else
 			psize = mmu_io_psize;
-		vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-			SLB_VSID_KERNEL;
+		slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
 		break;
 	case KERNEL_REGION_ID:
 		psize = mmu_linear_psize;
-		vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-			SLB_VSID_KERNEL;
+		slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
 		break;
 	default:
 		/* Future: support kernel segments so that drivers
@@ -215,11 +214,9 @@ static int __spu_trap_data_seg(struct sp
 		pr_debug("invalid region access at %016lx\n", ea);
 		return 1;
 	}
-	llp = mmu_psize_defs[psize].sllp;
+	slb.vsid |= mmu_psize_defs[psize].sllp;
 
-	out_be64(&priv2->slb_index_W, spu->slb_replace);
-	out_be64(&priv2->slb_vsid_RW, vsid | llp);
-	out_be64(&priv2->slb_esid_RW, esid);
+	spu_load_slb(spu, spu->slb_replace, &slb);
 
 	spu->slb_replace++;
 	if (spu->slb_replace >= 8)
#23 lore raw

PATCH 16/18 cell: add spu_64k_pages_available() check

In reply to [email protected]

Add a function spu_64k_pages_available(), so that we can abstract the explicity use of mmu_psize_defs() in lssca_alloc.c

---
 arch/powerpc/platforms/cell/spu_base.c          |    6 ++++++
 arch/powerpc/platforms/cell/spufs/lscsa_alloc.c |    2 +-
 include/asm-powerpc/spu.h                       |    1 +
 3 files changed, 8 insertions(+), 1 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +6 -0
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -126,6 +126,12 @@ void spu_associate_mm(struct spu *spu, s
 }
 EXPORT_SYMBOL_GPL(spu_associate_mm);
 
+int spu_64k_pages_available(void)
+{
+	return mmu_psize_defs[MMU_PAGE_64K].shift != 0;
+}
+EXPORT_SYMBOL_GPL(spu_64k_pages_available);
+
 static int __spu_trap_invalid_dma(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +1 -1
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
===================================================================
@@ -73,7 +73,7 @@ int spu_alloc_lscsa(struct spu_state *cs
 	int		i, j, n_4k;
 
 	/* Check availability of 64K pages */
-	if (mmu_psize_defs[MMU_PAGE_64K].shift == 0)
+	if (!spu_64k_pages_available())
 		goto fail;
 
 	csa->use_big_pages = 1;
include/asm-powerpc/spu.h +1 -0
Index: linux-2.6-new/include/asm-powerpc/spu.h
===================================================================
@@ -214,6 +214,7 @@ static inline void crash_register_spus(s
 
 extern void spu_invalidate_slbs(struct spu *spu);
 extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm);
+int spu_64k_pages_available(void);
 
 /* Calls from the memory management to the SPU */
 struct mm_struct;
#24 lore raw

PATCH 17/18 cell: handle SPE kernel mappings that cross segment boundaries

In reply to [email protected]

Currently, we have a possibilty that the SLBs setup during context switch don't cover the entirety of the necessary lscsa and code regions, if these regions cross a segment boundary.

This change checks the start and end of each region, and inserts a SLB entry for each, if unique. We also remove the assumption that the spu_save_code and spu_restore_code reside in the same segment, by using the specific code array for save and restore.

---
 arch/powerpc/platforms/cell/spu_base.c     |   50 ++++++++++++++++++++++++----
 arch/powerpc/platforms/cell/spufs/switch.c |   11 ++++--
 include/asm-powerpc/spu.h                  |    4 +-
 3 files changed, 52 insertions(+), 13 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +43 -7
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -275,19 +275,55 @@ static void __spu_kernel_slb(void *addr,
 }
 
 /**
+ * Given an array of @nr_slbs SLB entries, @slbs, return non-zero if the
+ * address @new_addr is present.
+ */
+static inline int __slb_present(struct spu_slb *slbs, int nr_slbs,
+		void *new_addr)
+{
+	unsigned long ea = (unsigned long)new_addr;
+	int i;
+
+	for (i = 0; i < nr_slbs; i++)
+		if (!((slbs[i].esid ^ ea) & ESID_MASK))
+			return 1;
+
+	return 0;
+}
+
+/**
  * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
  * need to map both the context save area, and the save/restore code.
+ *
+ * Because the lscsa and code may cross segment boundaires, we check to see
+ * if mappings are required for the start and end of each range. We currently
+ * assume that the mappings are smaller that one segment - if not, something
+ * is seriously wrong.
  */
-void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, void *code)
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size)
 {
-	struct spu_slb code_slb, lscsa_slb;
+	struct spu_slb slbs[4];
+	int i, nr_slbs = 0;
+	/* start and end addresses of both mappings */
+	void *addrs[] = {
+		lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
+		code, code + code_size - 1
+	};
 
-	__spu_kernel_slb(lscsa, &lscsa_slb);
-	__spu_kernel_slb(code, &code_slb);
+	/* check the set of addresses, and create a new entry in the slbs array
+	 * if there isn't already a SLB for that address */
+	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+		if (__slb_present(slbs, nr_slbs, addrs[i]))
+			continue;
+
+		__spu_kernel_slb(addrs[i], &slbs[nr_slbs]);
+		nr_slbs++;
+	}
 
-	spu_load_slb(spu, 0, &lscsa_slb);
-	if (lscsa_slb.esid != code_slb.esid)
-		spu_load_slb(spu, 1, &code_slb);
+	/* Add the set of SLBs */
+	for (i = 0; i < nr_slbs; i++)
+		spu_load_slb(spu, i, &slbs[i]);
 }
 EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
 
arch/powerpc/platforms/cell/spufs/switch.c +7 -4
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/switch.c
===================================================================
@@ -691,7 +691,8 @@ static inline void resume_mfc_queue(stru
 	out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
+static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu,
+		unsigned int *code, int code_size)
 {
 	/* Save, Step 47:
 	 * Restore, Step 30.
@@ -708,7 +709,7 @@ static inline void setup_mfc_slbs(struct
 	 *     translation is desired by OS environment).
 	 */
 	spu_invalidate_slbs(spu);
-	spu_setup_kernel_slbs(spu, csa->lscsa, &spu_save_code);
+	spu_setup_kernel_slbs(spu, csa->lscsa, code, code_size);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
@@ -1835,7 +1836,8 @@ static void save_lscsa(struct spu_state 
 	 */
 
 	resume_mfc_queue(prev, spu);	/* Step 46. */
-	setup_mfc_slbs(prev, spu);	/* Step 47. */
+	/* Step 47. */
+	setup_mfc_slbs(prev, spu, spu_save_code, sizeof(spu_save_code));
 	set_switch_active(prev, spu);	/* Step 48. */
 	enable_interrupts(prev, spu);	/* Step 49. */
 	save_ls_16kb(prev, spu);	/* Step 50. */
@@ -1940,7 +1942,8 @@ static void restore_lscsa(struct spu_sta
 	setup_spu_status_part1(next, spu);	/* Step 27. */
 	setup_spu_status_part2(next, spu);	/* Step 28. */
 	restore_mfc_rag(next, spu);	        /* Step 29. */
-	setup_mfc_slbs(next, spu);	        /* Step 30. */
+	/* Step 30. */
+	setup_mfc_slbs(next, spu, spu_restore_code, sizeof(spu_restore_code));
 	set_spu_npc(next, spu);	                /* Step 31. */
 	set_signot1(next, spu);	                /* Step 32. */
 	set_signot2(next, spu);	                /* Step 33. */
include/asm-powerpc/spu.h +2 -2
Index: linux-2.6-new/include/asm-powerpc/spu.h
===================================================================
@@ -201,8 +201,8 @@ int spu_irq_class_0_bottom(struct spu *s
 int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
-void spu_setup_kernel_slbs(struct spu *spu,
-		struct spu_lscsa *lscsa, void *code);
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size);
 
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);
#25 lore raw

PATCH 18/18 cell: catch errors from sysfs_create_group()

In reply to [email protected]

We're currently getting a warning from not checking the result of sysfs_create_group, which is declared as __must_check.

This change introduces appropriate error-handling for spu_add_sysdev_attr_group()

---
 arch/powerpc/platforms/cell/spu_base.c |   20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)
arch/powerpc/platforms/cell/spu_base.c +17 -3
Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
@@ -574,13 +574,27 @@ EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
 int spu_add_sysdev_attr_group(struct attribute_group *attrs)
 {
 	struct spu *spu;
+	int rc = 0;
 
 	mutex_lock(&spu_full_list_mutex);
-	list_for_each_entry(spu, &spu_full_list, full_list)
-		sysfs_create_group(&spu->sysdev.kobj, attrs);
+	list_for_each_entry(spu, &spu_full_list, full_list) {
+		rc = sysfs_create_group(&spu->sysdev.kobj, attrs);
+
+		/* we're in trouble here, but try unwinding anyway */
+		if (rc) {
+			printk(KERN_ERR "%s: can't create sysfs group '%s'\n",
+					__func__, attrs->name);
+
+			list_for_each_entry_continue_reverse(spu,
+					&spu_full_list, full_list)
+				sysfs_remove_group(&spu->sysdev.kobj, attrs);
+			break;
+		}
+	}
+
 	mutex_unlock(&spu_full_list_mutex);
 
-	return 0;
+	return rc;
 }
 EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
 
#26 lore raw
In reply to [email protected]
Quoted 3 lines · On Tuesday 18 December 2007, [email protected] wrote:

Paul, if there are no objections to these patches, please pull them from =20
=A0 git://git.kernel.org/pub/scm/linux/kernel/git/arnd/cell-2.6.git for-2=

=2E6.25

I just noticed that quilt ate the 'From' lines from the patches when sending them out, so make sure you don't apply them from mail. The git tree is fine, so I can send them out as patches again if necessary.

	Arnd <><
#27 lore raw
In reply to [email protected]
Quoted 3 lines · On Tuesday 18 December 2007, [email protected] wrote:

Paul, if there are no objections to these patches, please pull them from =20
=A0 git://git.kernel.org/pub/scm/linux/kernel/git/arnd/cell-2.6.git for-2=

=2E6.25

Quoted 1 line

=20

As Michael just told me on IRC, he's still working on a newer version of patches 4-10. I consequently updated my git tree to only contain patches 1-3 and 11-18 of this series.

	Arnd <><