* [PATCH 06/10] pmi probe device by device-type
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
At the moment the pmi device driver is probing for devices with
a given type and a given name. As there may be devices of
the same type but with a different name, probing should be
done also for device type only.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/sysdev/pmi.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/pmi.c
+++ linux-2.6/arch/powerpc/sysdev/pmi.c
@@ -118,6 +118,7 @@ out:
static struct of_device_id pmi_match[] = {
{ .type = "ibm,pmi", .name = "ibm,pmi" },
+ { .type = "ibm,pmi" },
{},
};
--
^ permalink raw reply
* [PATCH 02/10] cbe_thermal: clean up computation of temperature
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch introduces a little function for transforming
register values into temperature.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_thermal.c
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -31,6 +31,11 @@
#include "cbe_regs.h"
#include "spu_priv1_mmio.h"
+static inline u8 reg_to_temp(u8 reg_value)
+{
+ return ((reg_value & 0x3f) << 1) + 65;
+}
+
static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
{
struct spu *spu;
@@ -58,20 +63,14 @@ static u8 spu_read_register_value(struct
static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
{
- int value;
+ u8 value;
struct cbe_pmd_regs __iomem *pmd_regs;
pmd_regs = get_pmd_regs(sysdev);
value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
- /* clear all other bits */
- value &= 0x3F;
- /* temp is stored in steps of 2 degrees */
- value *= 2;
- /* base temp is 65 degrees */
- value += 65;
- return sprintf(buf, "%d\n", (int) value);
+ return sprintf(buf, "%d\n", reg_to_temp(value));
}
static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
@@ -82,16 +81,9 @@ static ssize_t ppe_show_temp(struct sys_
pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
value = in_be64(&pmd_regs->ts_ctsr2);
- /* access the corresponding byte */
- value >>= pos;
- /* clear all other bits */
- value &= 0x3F;
- /* temp is stored in steps of 2 degrees */
- value *= 2;
- /* base temp is 65 degrees */
- value += 65;
+ value = (value >> pos) & 0x3f;
- return sprintf(buf, "%d\n", (int) value);
+ return sprintf(buf, "%d\n", reg_to_temp(value));
}
--
^ permalink raw reply
* [PATCH 05/10] add check for initialized driver data to pmi driver
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds a check for the private driver data to be initialized.
The bug showed up, as the caller found a pmi device by it's type.
Whereas the pmi driver probes for the type and the name.
Since the name was not as the driver expected, it did not initialize.
A more relaxed probing will be supplied with an extra patch, too.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/sysdev/pmi.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/pmi.c
+++ linux-2.6/arch/powerpc/sysdev/pmi.c
@@ -279,6 +279,9 @@ void pmi_register_handler(struct of_devi
struct pmi_data *data;
data = device->dev.driver_data;
+ if (!data)
+ return;
+
spin_lock(&data->handler_spinlock);
list_add_tail(&handler->node, &data->handler);
spin_unlock(&data->handler_spinlock);
@@ -289,10 +292,12 @@ void pmi_unregister_handler(struct of_de
struct pmi_handler *handler)
{
struct pmi_data *data;
+ data = device->dev.driver_data;
- pr_debug("pmi: unregistering handler %p\n", handler);
+ if (!data)
+ return;
- data = device->dev.driver_data;
+ pr_debug("pmi: unregistering handler %p\n", handler);
spin_lock(&data->handler_spinlock);
list_del(&handler->node);
--
^ permalink raw reply
* [PATCH 08/10] cell: add support for proper device-tree
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds support for a proper device-tree.
A porper device-tree on cell contains be nodes
for each CBE containg nodes for SPEs and all the
other special devices on it.
Ofcourse oldschool devicetree is still supported.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_regs.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_regs.c
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_regs.c
@@ -14,6 +14,8 @@
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include "cbe_regs.h"
@@ -27,6 +29,7 @@
static struct cbe_regs_map
{
struct device_node *cpu_node;
+ struct device_node *be_node;
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_iic_regs __iomem *iic_regs;
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
@@ -37,6 +40,7 @@ static int cbe_regs_map_count;
static struct cbe_thread_map
{
struct device_node *cpu_node;
+ struct device_node *be_node;
struct cbe_regs_map *regs;
unsigned int thread_id;
unsigned int cbe_id;
@@ -50,22 +54,29 @@ static struct cbe_regs_map *cbe_find_map
int i;
struct device_node *tmp_np;
- if (strcasecmp(np->type, "spe") == 0) {
- if (np->data == NULL) {
- /* walk up path until cpu node was found */
- tmp_np = np->parent;
- while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0)
- tmp_np = tmp_np->parent;
+ if (strcasecmp(np->type, "spe")) {
+ for (i = 0; i < cbe_regs_map_count; i++)
+ if (cbe_regs_maps[i].cpu_node == np ||
+ cbe_regs_maps[i].be_node == np)
+ return &cbe_regs_maps[i];
+ return NULL;
+ }
- np->data = cbe_find_map(tmp_np);
- }
+ if (np->data)
return np->data;
- }
- for (i = 0; i < cbe_regs_map_count; i++)
- if (cbe_regs_maps[i].cpu_node == np)
- return &cbe_regs_maps[i];
- return NULL;
+ /* walk up path until cpu or be node was found */
+ tmp_np = np;
+ do {
+ tmp_np = tmp_np->parent;
+ /* on a correct devicetree we wont get up to root */
+ BUG_ON(!tmp_np);
+ } while (strcasecmp(tmp_np->type, "cpu") &&
+ strcasecmp(tmp_np->type, "be"));
+
+ np->data = cbe_find_map(tmp_np);
+
+ return np->data;
}
struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
@@ -153,6 +164,67 @@ u32 cbe_node_to_cpu(int node)
}
EXPORT_SYMBOL_GPL(cbe_node_to_cpu);
+static struct device_node *cbe_get_be_node(int cpu_id)
+{
+ struct device_node *np;
+
+ for_each_node_by_type (np, "be") {
+ int len,i;
+ const phandle *cpu_handle;
+
+ cpu_handle = of_get_property(np, "cpus", &len);
+
+ for (i=0; i<len; i++)
+ if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL))
+ return np;
+ }
+
+ return NULL;
+}
+
+void __init cbe_fill_regs_map(struct cbe_regs_map *map)
+{
+ if(map->be_node) {
+ struct device_node *be, *np;
+
+ be = map->be_node;
+
+ for_each_node_by_type(np, "pervasive")
+ if (of_get_parent(np) == be)
+ map->pmd_regs = of_iomap(np, 0);
+
+ for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller")
+ if (of_get_parent(np) == be)
+ map->iic_regs = of_iomap(np, 2);
+
+ for_each_node_by_type(np, "mic-tm")
+ if (of_get_parent(np) == be)
+ map->mic_tm_regs = of_iomap(np, 0);
+ } else {
+ struct device_node *cpu;
+ /* That hack must die die die ! */
+ const struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *prop;
+
+ cpu = map->cpu_node;
+
+ prop = of_get_property(cpu, "pervasive", NULL);
+ if (prop != NULL)
+ map->pmd_regs = ioremap(prop->address, prop->len);
+
+ prop = of_get_property(cpu, "iic", NULL);
+ if (prop != NULL)
+ map->iic_regs = ioremap(prop->address, prop->len);
+
+ prop = of_get_property(cpu, "mic-tm", NULL);
+ if (prop != NULL)
+ map->mic_tm_regs = ioremap(prop->address, prop->len);
+ }
+}
+
+
void __init cbe_regs_init(void)
{
int i;
@@ -162,6 +234,7 @@ void __init cbe_regs_init(void)
/* Build local fast map of CPUs */
for_each_possible_cpu(i) {
cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id);
+ cbe_thread_map[i].be_node = cbe_get_be_node(i);
cbe_thread_map[i].thread_id = thread_id;
}
@@ -170,12 +243,6 @@ void __init cbe_regs_init(void)
struct cbe_regs_map *map;
unsigned int cbe_id;
- /* That hack must die die die ! */
- const struct address_prop {
- unsigned long address;
- unsigned int len;
- } __attribute__((packed)) *prop;
-
cbe_id = cbe_regs_map_count++;
map = &cbe_regs_maps[cbe_id];
@@ -193,23 +260,14 @@ void __init cbe_regs_init(void)
if (thread->cpu_node == cpu) {
thread->regs = map;
thread->cbe_id = cbe_id;
+ map->be_node = thread->be_node;
cpu_set(i, cbe_local_mask[cbe_id]);
if(thread->thread_id == 0)
cpu_set(i, cbe_first_online_cpu);
}
}
- prop = of_get_property(cpu, "pervasive", NULL);
- if (prop != NULL)
- map->pmd_regs = ioremap(prop->address, prop->len);
-
- prop = of_get_property(cpu, "iic", NULL);
- if (prop != NULL)
- map->iic_regs = ioremap(prop->address, prop->len);
-
- prop = of_get_property(cpu, "mic-tm", NULL);
- if (prop != NULL)
- map->mic_tm_regs = ioremap(prop->address, prop->len);
+ cbe_fill_regs_map(map);
}
}
--
^ permalink raw reply
* [PATCH 03/10] cbe_thermal: add throttling attributes to cpu and spu nodes
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds some attributes the cpu and spu nodes:
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_begin
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_end
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_full_stop
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_thermal.c
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -1,6 +1,31 @@
/*
* thermal support for the cell processor
*
+ * This module adds some sysfs attributes to cpu and spu nodes.
+ * Base for measurements are the digital thermal sensors (DTS)
+ * located on the chip.
+ * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius
+ * The attributes can be found under
+ * /sys/devices/system/cpu/cpuX/thermal
+ * /sys/devices/system/spu/spuX/thermal
+ *
+ * The following attributes are added for each node:
+ * temperature:
+ * contains the current temperature measured by the DTS
+ * throttle_begin:
+ * throttling begins when temperature is greater or equal to
+ * throttle_begin. Setting this value to 125 prevents throttling.
+ * throttle_end:
+ * throttling is being ceased, if the temperature is lower than
+ * throttle_end. Due to a delay between applying throttling and
+ * a reduced temperature this value should be less than throttle_begin.
+ * A value equal to throttle_begin provides only a very little hysteresis.
+ * throttle_full_stop:
+ * If the temperatrue is greater or equal to throttle_full_stop,
+ * full throttling is applied to the cpu or spu. This value should be
+ * greater than throttle_begin and throttle_end. Setting this value to
+ * 65 prevents the unit from running code at all.
+ *
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
*
* Author: Christian Krafft <krafft@de.ibm.com>
@@ -31,9 +56,24 @@
#include "cbe_regs.h"
#include "spu_priv1_mmio.h"
+#define TEMP_MIN 65
+#define TEMP_MAX 125
+
+#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \
+struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
+ .show = _prefix ## _show_ ## _name, \
+ .store = _prefix ## _store_ ## _name, \
+};
+
static inline u8 reg_to_temp(u8 reg_value)
{
- return ((reg_value & 0x3f) << 1) + 65;
+ return ((reg_value & 0x3f) << 1) + TEMP_MIN;
+}
+
+static inline u8 temp_to_reg(u8 temp)
+{
+ return ((temp - TEMP_MIN) >> 1) & 0x3f;
}
static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
@@ -73,6 +113,73 @@ static ssize_t spu_show_temp(struct sys_
return sprintf(buf, "%d\n", reg_to_temp(value));
}
+static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos)
+{
+ u64 value;
+
+ value = in_be64(&pmd_regs->tm_tpr.val);
+ /* access the corresponding byte */
+ value >>= pos;
+ value &= 0x3F;
+
+ return sprintf(buf, "%d\n", reg_to_temp(value));
+}
+
+static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos)
+{
+ u64 reg_value;
+ int temp;
+ u64 new_value;
+ int ret;
+
+ ret = sscanf(buf, "%u", &temp);
+
+ if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX)
+ return -EINVAL;
+
+ new_value = temp_to_reg(temp);
+
+ reg_value = in_be64(&pmd_regs->tm_tpr.val);
+
+ /* zero out bits for new value */
+ reg_value &= ~(0xffull << pos);
+ /* set bits to new value */
+ reg_value |= new_value << pos;
+
+ out_be64(&pmd_regs->tm_tpr.val, reg_value);
+ return size;
+}
+
+static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 0);
+}
+
+static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 8);
+}
+
+static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 16);
+}
+
+static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 0);
+}
+
+static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 8);
+}
+
+static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 16);
+}
+
static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
{
struct cbe_pmd_regs __iomem *pmd_regs;
@@ -100,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys
return ppe_show_temp(sysdev, buf, 0);
}
+static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32);
+}
+
+static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40);
+}
+
+static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48);
+}
+
+static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32);
+}
+
+static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40);
+}
+
+static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48);
+}
+
+
static struct sysdev_attribute attr_spu_temperature = {
.attr = {.name = "temperature", .mode = 0400 },
.show = spu_show_temp,
};
+static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600);
+static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600);
+static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600);
+
+
static struct attribute *spu_attributes[] = {
&attr_spu_temperature.attr,
+ &attr_spu_throttle_end.attr,
+ &attr_spu_throttle_begin.attr,
+ &attr_spu_throttle_full_stop.attr,
NULL,
};
@@ -125,9 +271,16 @@ static struct sysdev_attribute attr_ppe_
.show = ppe_show_temp1,
};
+static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600);
+static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600);
+static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
+
static struct attribute *ppe_attributes[] = {
&attr_ppe_temperature0.attr,
&attr_ppe_temperature1.attr,
+ &attr_ppe_throttle_end.attr,
+ &attr_ppe_throttle_begin.attr,
+ &attr_ppe_throttle_full_stop.attr,
NULL,
};
--
^ permalink raw reply
* [PATCH 04/10] cell: use pmi in cpufreq driver
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
The new PMI driver was added in order to support
cpufreq on blades that require the frequency to
be controlled by the service processor, so use it
on those.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -28,6 +28,8 @@
#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/time.h>
+#include <asm/pmi.h>
+#include <asm/of_platform.h>
#include "cbe_regs.h"
@@ -68,6 +70,38 @@ static u64 MIC_Slow_Next_Timer_table[] =
* hardware specific functions
*/
+static struct of_device *pmi_dev;
+
+static int set_pmode_pmi(int cpu, unsigned int pmode)
+{
+ int ret;
+ pmi_message_t pmi_msg;
+#ifdef DEBUG
+ u64 time;
+#endif
+
+ pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
+ pmi_msg.data1 = cbe_cpu_to_node(cpu);
+ pmi_msg.data2 = pmode;
+
+#ifdef DEBUG
+ time = (u64) get_cycles();
+#endif
+
+ pmi_send_message(pmi_dev, pmi_msg);
+ ret = pmi_msg.data2;
+
+ pr_debug("PMI returned slow mode %d\n", ret);
+
+#ifdef DEBUG
+ time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */
+ time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */
+ pr_debug("had to wait %lu ns for a transition\n", time);
+#endif
+ return ret;
+}
+
+
static int get_pmode(int cpu)
{
int ret;
@@ -79,7 +113,7 @@ static int get_pmode(int cpu)
return ret;
}
-static int set_pmode(int cpu, unsigned int pmode)
+static int set_pmode_reg(int cpu, unsigned int pmode)
{
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
@@ -120,6 +154,39 @@ static int set_pmode(int cpu, unsigned i
return 0;
}
+static int set_pmode(int cpu, unsigned int slow_mode) {
+ if(pmi_dev)
+ return set_pmode_pmi(cpu, slow_mode);
+ else
+ return set_pmode_reg(cpu, slow_mode);
+}
+
+static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
+{
+ struct cpufreq_policy policy;
+ u8 cpu;
+ u8 cbe_pmode_new;
+
+ BUG_ON (pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
+
+ cpu = cbe_node_to_cpu(pmi_msg.data1);
+ cbe_pmode_new = pmi_msg.data2;
+
+ cpufreq_get_policy(&policy, cpu);
+
+ policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency);
+ policy.min = min(policy.min, policy.max);
+
+ pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max);
+ cpufreq_set_policy(&policy);
+}
+
+static struct pmi_handler cbe_pmi_handler = {
+ .type = PMI_TYPE_FREQ_CHANGE,
+ .handle_pmi_message = cbe_cpufreq_handle_pmi,
+};
+
+
/*
* cpufreq functions
*/
@@ -234,11 +301,23 @@ static struct cpufreq_driver cbe_cpufreq
static int __init cbe_cpufreq_init(void)
{
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ibm,pmi");
+
+ pmi_dev = of_find_device_by_node(np);
+
+ if (pmi_dev)
+ pmi_register_handler(pmi_dev, &cbe_pmi_handler);
+
return cpufreq_register_driver(&cbe_cpufreq_driver);
}
static void __exit cbe_cpufreq_exit(void)
{
+ if(pmi_dev)
+ pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
+
cpufreq_unregister_driver(&cbe_cpufreq_driver);
}
--
^ permalink raw reply
* [PATCH 07/10] add of_iomap function
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
The of_iomap function maps memory for a given
device_node and returns a pointer to that memory.
This is used at some places, so it makes sense to
a seperate function.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/sysdev/pmi.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/pmi.c
+++ linux-2.6/arch/powerpc/sysdev/pmi.c
@@ -33,7 +33,7 @@
#include <asm/of_platform.h>
#include <asm/io.h>
#include <asm/pmi.h>
-
+#include <asm/prom.h>
struct pmi_data {
struct list_head handler;
@@ -49,21 +49,6 @@ struct pmi_data {
};
-
-static void __iomem *of_iomap(struct device_node *np)
-{
- struct resource res;
-
- if (of_address_to_resource(np, 0, &res))
- return NULL;
-
- pr_debug("Resource start: 0x%lx\n", res.start);
- pr_debug("Resource end: 0x%lx\n", res.end);
-
- return ioremap(res.start, 1 + res.end - res.start);
-}
-
-
static int pmi_irq_handler(int irq, void *dev_id)
{
struct pmi_data *data;
@@ -154,7 +139,7 @@ static int pmi_of_probe(struct of_device
goto out;
}
- data->pmi_reg = of_iomap(np);
+ data->pmi_reg = of_iomap(np, 0);
if (!data->pmi_reg) {
printk(KERN_ERR "pmi: invalid register address.\n");
rc = -EFAULT;
Index: linux-2.6/include/asm-powerpc/prom.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/prom.h
+++ linux-2.6/include/asm-powerpc/prom.h
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/atomic.h>
+#include <asm/io.h>
/* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */
@@ -355,6 +356,16 @@ static inline int of_irq_to_resource(str
return irq;
}
+static inline void __iomem *of_iomap(struct device_node *np, int index)
+{
+ struct resource res;
+
+ if (of_address_to_resource(np, index, &res))
+ return NULL;
+
+ return ioremap(res.start, 1 + res.end - res.start);
+}
+
#endif /* __KERNEL__ */
#endif /* _POWERPC_PROM_H */
--
^ permalink raw reply
* [PATCH 01/10] cell: add cbe_node_to_cpu function
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds code to deal with conversion of
logical cpu to cbe nodes. It removes code that
assummed there were two logical CPUs per CBE.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_regs.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_regs.c
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_regs.c
@@ -38,8 +38,13 @@ static struct cbe_thread_map
{
struct device_node *cpu_node;
struct cbe_regs_map *regs;
+ unsigned int thread_id;
+ unsigned int cbe_id;
} cbe_thread_map[NR_CPUS];
+static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE };
+static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE;
+
static struct cbe_regs_map *cbe_find_map(struct device_node *np)
{
int i;
@@ -130,31 +135,40 @@ struct cbe_mic_tm_regs __iomem *cbe_get_
}
EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs);
-/* FIXME
- * This is little more than a stub at the moment. It should be
- * fleshed out so that it works for both SMT and non-SMT, no
- * matter if the passed cpu is odd or even.
- * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1.
- * For SMT disabled, returns 0 for all cpus.
- */
u32 cbe_get_hw_thread_id(int cpu)
{
- return (cpu & 1);
+ return cbe_thread_map[cpu].thread_id;
}
EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id);
+u32 cbe_cpu_to_node(int cpu)
+{
+ return cbe_thread_map[cpu].cbe_id;
+}
+EXPORT_SYMBOL_GPL(cbe_cpu_to_node);
+
+u32 cbe_node_to_cpu(int node)
+{
+ return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t));
+}
+EXPORT_SYMBOL_GPL(cbe_node_to_cpu);
+
void __init cbe_regs_init(void)
{
int i;
+ unsigned int thread_id;
struct device_node *cpu;
/* Build local fast map of CPUs */
- for_each_possible_cpu(i)
- cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
+ for_each_possible_cpu(i) {
+ cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id);
+ cbe_thread_map[i].thread_id = thread_id;
+ }
/* Find maps for each device tree CPU */
for_each_node_by_type(cpu, "cpu") {
- struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
+ struct cbe_regs_map *map;
+ unsigned int cbe_id;
/* That hack must die die die ! */
const struct address_prop {
@@ -162,6 +176,8 @@ void __init cbe_regs_init(void)
unsigned int len;
} __attribute__((packed)) *prop;
+ cbe_id = cbe_regs_map_count++;
+ map = &cbe_regs_maps[cbe_id];
if (cbe_regs_map_count > MAX_CBE) {
printk(KERN_ERR "cbe_regs: More BE chips than supported"
@@ -170,9 +186,18 @@ void __init cbe_regs_init(void)
return;
}
map->cpu_node = cpu;
- for_each_possible_cpu(i)
- if (cbe_thread_map[i].cpu_node == cpu)
- cbe_thread_map[i].regs = map;
+
+ for_each_possible_cpu(i) {
+ struct cbe_thread_map *thread = &cbe_thread_map[i];
+
+ if (thread->cpu_node == cpu) {
+ thread->regs = map;
+ thread->cbe_id = cbe_id;
+ cpu_set(i, cbe_local_mask[cbe_id]);
+ if(thread->thread_id == 0)
+ cpu_set(i, cbe_first_online_cpu);
+ }
+ }
prop = of_get_property(cpu, "pervasive", NULL);
if (prop != NULL)
Index: linux-2.6/arch/powerpc/platforms/cell/cbe_regs.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_regs.h
+++ linux-2.6/arch/powerpc/platforms/cell/cbe_regs.h
@@ -255,6 +255,11 @@ struct cbe_mic_tm_regs {
extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
+/* some utility functions to deal with SMT */
+extern u32 cbe_get_hw_thread_id(int cpu);
+extern u32 cbe_cpu_to_node(int cpu);
+extern u32 cbe_node_to_cpu(int node);
+
/* Init this module early */
extern void cbe_regs_init(void);
Index: linux-2.6/arch/powerpc/oprofile/op_model_cell.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/op_model_cell.c
+++ linux-2.6/arch/powerpc/oprofile/op_model_cell.c
@@ -37,6 +37,7 @@
#include <asm/system.h>
#include "../platforms/cell/interrupt.h"
+#include "../platforms/cell/cbe_regs.h"
#define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */
#define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying
Index: linux-2.6/include/asm-powerpc/cell-pmu.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/cell-pmu.h
+++ linux-2.6/include/asm-powerpc/cell-pmu.h
@@ -97,11 +97,6 @@ extern void cbe_disable_pm_interrupts(u3
extern u32 cbe_get_and_clear_pm_interrupts(u32 cpu);
extern void cbe_sync_irq(int node);
-/* Utility functions, macros */
-extern u32 cbe_get_hw_thread_id(int cpu);
-
-#define cbe_cpu_to_node(cpu) ((cpu) >> 1)
-
#define CBE_COUNT_SUPERVISOR_MODE 0
#define CBE_COUNT_HYPERVISOR_MODE 1
#define CBE_COUNT_PROBLEM_MODE 2
--
^ permalink raw reply
* [PATCH 00/10] non-spufs updates for cell platforms
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
These are mostly about power management and other features of specific
IBM blades. Please pull from
ssh://master.kernel.org/pub/scm/linux/kernel/git/arnd/cell-2.6.git for-2.6.22
Arnd <><
---
arch/powerpc/configs/cell_defconfig | 57 ++++-----
arch/powerpc/oprofile/op_model_cell.c | 1
arch/powerpc/platforms/cell/cbe_cpufreq.c | 81 +++++++++++++
arch/powerpc/platforms/cell/cbe_regs.c | 165 +++++++++++++++++++++------
arch/powerpc/platforms/cell/cbe_regs.h | 5
arch/powerpc/platforms/cell/cbe_thermal.c | 177 +++++++++++++++++++++++++++---
arch/powerpc/platforms/cell/ras.c | 160 +++++++++++++++++++++++++++
arch/powerpc/sysdev/pmi.c | 29 +---
include/asm-powerpc/cell-pmu.h | 5
include/asm-powerpc/prom.h | 11 +
10 files changed, 581 insertions(+), 110 deletions(-)
^ permalink raw reply
* [PATCH 2/4 v3] powerpc: replace undocumented interface properties in dts files
From: Kim Phillips @ 2007-04-23 19:40 UTC (permalink / raw)
To: linuxppc-dev
phy-connection-type now supercedes the interface property.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---
name change since [patch 2/4 v2]: s/interface-type/phy-connection-type/g
arch/powerpc/boot/dts/mpc832x_mds.dts | 2 --
arch/powerpc/boot/dts/mpc832x_rdb.dts | 2 --
arch/powerpc/boot/dts/mpc836x_mds.dts | 4 ++--
arch/powerpc/boot/dts/mpc8568mds.dts | 6 ++----
4 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index c798491..93b7606 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -306,14 +306,12 @@
interrupts = <11 8>;
reg = <3>;
device_type = "ethernet-phy";
- interface = <3>; //ENET_100_MII
};
phy4: ethernet-phy@04 {
interrupt-parent = < &ipic >;
interrupts = <12 8>;
reg = <4>;
device_type = "ethernet-phy";
- interface = <3>;
};
};
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index b55bced..be4c357 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -265,14 +265,12 @@
interrupts = <0>;
reg = <0>;
device_type = "ethernet-phy";
- interface = <3>; //ENET_100_MII
};
phy04:ethernet-phy@04 {
interrupt-parent = <&pic>;
interrupts = <0>;
reg = <4>;
device_type = "ethernet-phy";
- interface = <3>;
};
};
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 7f578eb..67622f2 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -302,6 +302,7 @@
interrupts = <20>;
interrupt-parent = < &qeic >;
mac-address = [ 00 04 9f 00 23 23 ];
+ phy-connection-type = "rgmii-id";
rx-clock = <0>;
tx-clock = <19>;
phy-handle = < &phy0 >;
@@ -317,6 +318,7 @@
interrupts = <21>;
interrupt-parent = < &qeic >;
mac-address = [ 00 11 22 33 44 55 ];
+ phy-connection-type = "rgmii-id";
rx-clock = <0>;
tx-clock = <14>;
phy-handle = < &phy1 >;
@@ -335,14 +337,12 @@
interrupts = <11 8>;
reg = <0>;
device_type = "ethernet-phy";
- interface = <6>; //ENET_1000_GMII
};
phy1: ethernet-phy@01 {
interrupt-parent = < &ipic >;
interrupts = <12 8>;
reg = <1>;
device_type = "ethernet-phy";
- interface = <6>;
};
};
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 7361b36..14e3ea6 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -285,6 +285,7 @@
interrupts = <20>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f 00 23 23 ];
+ phy-connection-type = "gmii";
rx-clock = <0>;
tx-clock = <19>;
phy-handle = <&qe_phy0>;
@@ -300,6 +301,7 @@
interrupts = <21>;
interrupt-parent = <&qeic>;
mac-address = [ 00 11 22 33 44 55 ];
+ phy-connection-type = "gmii";
rx-clock = <0>;
tx-clock = <14>;
phy-handle = <&qe_phy1>;
@@ -320,28 +322,24 @@
interrupts = <31 1>;
reg = <0>;
device_type = "ethernet-phy";
- interface = <6>; //ENET_1000_GMII
};
qe_phy1: ethernet-phy@01 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <1>;
device_type = "ethernet-phy";
- interface = <6>;
};
qe_phy2: ethernet-phy@02 {
interrupt-parent = <&mpic>;
interrupts = <31 1>;
reg = <2>;
device_type = "ethernet-phy";
- interface = <6>; //ENET_1000_GMII
};
qe_phy3: ethernet-phy@03 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <3>;
device_type = "ethernet-phy";
- interface = <6>; //ENET_1000_GMII
};
};
--
1.5.0.3
^ permalink raw reply related
* [PATCH 1/4 v4] powerpc: document phy-connection-type property
From: Kim Phillips @ 2007-04-23 19:40 UTC (permalink / raw)
To: linuxppc-dev
Since ucc_geth is being migrated to use the phylib, the existing
(undocumented) 'interface' property is being deprecated in favour
of 'phy-connection-type'.
phy-connection-type is now maintained one-to-one with definitions
in include/linux/phy.h, albeit in the form of a string.
If not specified, "mii" is assumed.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---
name change since [patch 1/4 v3]: s/interface-type/phy-connection-type/g
Documentation/powerpc/booting-without-of.txt | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 88cdb59..f9111cc 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1562,6 +1562,9 @@ platforms are moved over to use the flattened-device-tree model.
network device. This is used by the bootwrapper to interpret
MAC addresses passed by the firmware when no information other
than indices is available to associate an address with a device.
+ - phy-connection-type : a string naming the controller/PHY interface type,
+ i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "tbi",
+ or "rtbi".
Example:
ucc@2000 {
@@ -1573,6 +1576,7 @@ platforms are moved over to use the flattened-device-tree model.
interrupts = <a0 0>;
interrupt-parent = <700>;
mac-address = [ 00 04 9f 00 23 23 ];
+ phy-connection-type = "gmii";
rx-clock = "none";
tx-clock = "clk9";
phy-handle = <212000>;
--
1.5.0.3
^ permalink raw reply related
* [PATCH 09/10] cell: enable RTAS-based PTCAL for Cell XDR memory
From: Arnd Bergmann @ 2007-04-23 19:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <20070423193538.576702568@arndb.de>
From: Jeremy Kerr <jk@ozlabs.org>
Enable Periodic Recalibration (PTCAL) support for Cell XDR memory,
using the new ibm,cbe-start-ptcal and ibm,cbe-stop-ptcal RTAS calls.
Tested on QS20 and QS21 (by Thomas Huth). It seems that SLOF has
problems disabling, at least on QS20; this patch should only be
used once these problems have been addressed.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
Update: Updated with Michael's feedback, expanded comment.
Index: linux-2.6/arch/powerpc/platforms/cell/ras.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/ras.c
+++ linux-2.6/arch/powerpc/platforms/cell/ras.c
@@ -3,11 +3,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
+#include <linux/reboot.h>
#include <asm/reg.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/rtas.h>
#include "ras.h"
#include "cbe_regs.h"
@@ -82,6 +84,164 @@ static int cbe_machine_check_handler(str
return 0;
}
+struct ptcal_area {
+ struct list_head list;
+ int nid;
+ int order;
+ struct page *pages;
+};
+
+static LIST_HEAD(ptcal_list);
+
+static int ptcal_start_tok, ptcal_stop_tok;
+
+static int __init cbe_ptcal_enable_on_node(int nid, int order)
+{
+ struct ptcal_area *area;
+ int ret = -ENOMEM;
+ unsigned long addr;
+
+#ifdef CONFIG_CRASH_DUMP
+ rtas_call(ptcal_stop_tok, 1, 1, NULL, nid);
+#endif
+
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
+ if (!area)
+ goto out_err;
+
+ area->nid = nid;
+ area->order = order;
+ area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order);
+
+ if (!area->pages)
+ goto out_free_area;
+
+ addr = __pa(page_address(area->pages));
+
+ ret = -EIO;
+ if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid,
+ (unsigned int)(addr >> 32),
+ (unsigned int)(addr & 0xffffffff))) {
+ printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n",
+ __FUNCTION__, nid);
+ goto out_free_pages;
+ }
+
+ list_add(&area->list, &ptcal_list);
+
+ return 0;
+
+out_free_pages:
+ __free_pages(area->pages, area->order);
+out_free_area:
+ kfree(area);
+out_err:
+ return ret;
+}
+
+static int __init cbe_ptcal_enable(void)
+{
+ const u32 *size;
+ struct device_node *np;
+ int order, found_mic = 0;
+
+ np = of_find_node_by_path("/rtas");
+ if (!np)
+ return -ENODEV;
+
+ size = get_property(np, "ibm,cbe-ptcal-size", NULL);
+ if (!size)
+ return -ENODEV;
+
+ pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size);
+ order = get_order(*size);
+ of_node_put(np);
+
+ /* support for malta device trees, with be@/mic@ nodes */
+ for_each_node_by_type(np, "mic-tm") {
+ cbe_ptcal_enable_on_node(of_node_to_nid(np), order);
+ found_mic = 1;
+ }
+
+ if (found_mic)
+ return 0;
+
+ /* support for older device tree - use cpu nodes */
+ for_each_node_by_type(np, "cpu") {
+ const u32 *nid = get_property(np, "node-id", NULL);
+ if (!nid) {
+ printk(KERN_ERR "%s: node %s is missing node-id?\n",
+ __FUNCTION__, np->full_name);
+ continue;
+ }
+ cbe_ptcal_enable_on_node(*nid, order);
+ found_mic = 1;
+ }
+
+ return found_mic ? 0 : -ENODEV;
+}
+
+static int cbe_ptcal_disable(void)
+{
+ struct ptcal_area *area, *tmp;
+ int ret = 0;
+
+ pr_debug("%s: disabling PTCAL\n", __FUNCTION__);
+
+ list_for_each_entry_safe(area, tmp, &ptcal_list, list) {
+ /* disable ptcal on this node */
+ if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) {
+ printk(KERN_ERR "%s: error disabling PTCAL "
+ "on node %d!\n", __FUNCTION__,
+ area->nid);
+ ret = -EIO;
+ continue;
+ }
+
+ /* ensure we can access the PTCAL area */
+ memset(page_address(area->pages), 0,
+ 1 << (area->order + PAGE_SHIFT));
+
+ /* clean up */
+ list_del(&area->list);
+ __free_pages(area->pages, area->order);
+ kfree(area);
+ }
+
+ return ret;
+}
+
+static int cbe_ptcal_notify_reboot(struct notifier_block *nb,
+ unsigned long code, void *data)
+{
+ return cbe_ptcal_disable();
+}
+
+static struct notifier_block cbe_ptcal_reboot_notifier = {
+ .notifier_call = cbe_ptcal_notify_reboot
+};
+
+int __init cbe_ptcal_init(void)
+{
+ int ret;
+ ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal");
+ ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal");
+
+ if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE
+ || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE)
+ return -ENODEV;
+
+ ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier);
+ if (ret) {
+ printk(KERN_ERR "Can't disable PTCAL, so not enabling\n");
+ return ret;
+ }
+
+ return cbe_ptcal_enable();
+}
+
+arch_initcall(cbe_ptcal_init);
+
void __init cbe_ras_init(void)
{
unsigned long hid0;
--
^ permalink raw reply
* Re: [PATCH] eHCA: Add "Modify Port" verb
From: Roland Dreier @ 2007-04-23 19:20 UTC (permalink / raw)
To: Joachim Fenkes; +Cc: LinuxPPC-Dev, LKML, OF-General
In-Reply-To: <200704231823.48723.fenkes@de.ibm.com>
> + if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
> + ehca_err(&shca->ib_device, "Can't query port properties");
> + ret = -EINVAL;
> + goto modify_port1;
> + }
> +
> + cap = (rblock->capability_mask | props->set_port_cap_mask)
> + & ~props->clr_port_cap_mask;
> +
> + hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
> + cap, props->init_type, port_modify_mask);
Is this thread-safe? What if two different bits are set at the same
time from two different threads? It seems that both calls could get
the same result from hipz_h_query_port(), and then the second call to
hipz_h_modify_port() would overwrite the first call.
You could look at the implementation in mthca to see the locking I
used there.
- R.
^ permalink raw reply
* Re: [PATCH] ib_core: Add missing device link to class device
From: Roland Dreier @ 2007-04-23 19:17 UTC (permalink / raw)
To: Joachim Fenkes; +Cc: LinuxPPC-Dev, LKML, OF-General
In-Reply-To: <200704231820.27752.fenkes@de.ibm.com>
Hmm, I have links like this on my system already:
$ ls -l /sys/class/infiniband/mlx4_0/device
lrwxrwxrwx 1 root root 0 2007-04-23 12:14 /sys/class/infiniband/mlx4_0/device -> ../../../devices/pci0000:00/0000:00:06.0/0000:0d:00.0
the patch actually looks sane but I don't understand why it's needed.
Could you explain?
^ permalink raw reply
* Re: Fw: [PATCH][RFC] PCMCIA support for 8xx using platform devices
From: Scott Wood @ 2007-04-23 19:07 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-dev@ozlabs.org, linux-pcmcia, lkml
In-Reply-To: <20070422232658.5f427fd3@localhost.localdomain>
On Sun, Apr 22, 2007 at 11:26:58PM +0400, Vitaly Bordug wrote:
> diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
> index 90e047a..330ac91 100644
> --- a/arch/powerpc/boot/dts/mpc885ads.dts
> +++ b/arch/powerpc/boot/dts/mpc885ads.dts
> @@ -112,6 +112,18 @@
> compatible = "CPM";
> };
>
> + pcmcia@0080 {
> + linux,phandle = <0080>;
> + #interrupt-cells = <1>;
> + #size-cells = <2>;
> + compatible = "8xx";
> + device_type = "pcmcia";
> + reg = <80 80>;
> + clock-frequency = <2faf080>;
> + interrupt-parent = <ff000000>;
> + interrupts = <d 1>;
> + };
> +
DTC supports labels now; we should be using those instead of hardcoded
phandles. Also, please indent by tabs.
-Scott
^ permalink raw reply
* Re: [PATCH] Start split out of common open firmware code
From: Segher Boessenkool @ 2007-04-23 18:30 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: paulus, David Miller, linuxppc-dev
In-Reply-To: <20070423174339.20308ac3.sfr@canb.auug.org.au>
>> drivers/ is the wrong place to put this IMHO. Why not
>> use kernel/openfirmware/*.[ch] ?
>
> We have drivers/acpi as a precedent ...
That doesn't mean it's a good place for firmware interface
code, it just means that the ACPI code currently lives
there :-)
Segher
^ permalink raw reply
* [patch 2/2] powerpc: pmi probe device by device-type
From: Christian Krafft @ 2007-04-23 18:22 UTC (permalink / raw)
To: linuxppc-dev; +Cc: krafft, cbe-oss-dev
[-- Attachment #1: Type: text/plain, Size: 1048 bytes --]
From: Christian Krafft <krafft@de.ibm.com>
At the moment the pmi device driver is probing for devices with
a given type and a given name. As there may be devices of
the same type but with a different name, probing should be
done also for device type only.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: sdk3/arch/powerpc/sysdev/pmi.c
===================================================================
--- sdk3.orig/arch/powerpc/sysdev/pmi.c
+++ sdk3/arch/powerpc/sysdev/pmi.c
@@ -103,6 +103,7 @@ out:
static struct of_device_id pmi_match[] = {
{ .type = "ibm,pmi", .name = "ibm,pmi" },
+ { .type = "ibm,pmi" },
{},
};
--
Mit freundlichen Gruessen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist
Vorsitzender des Aufsichtsrats: Johann Weihen
Geschaeftsfuehrung: Herbert Kircher
Sitz der Gesellschaft: Boeblingen
Registriergericht: Amtsgericht Stuttgart, HRB 243294
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [patch 1/2] powerpc: add check for initialized driver data to pmi driver
From: Christian Krafft @ 2007-04-23 18:22 UTC (permalink / raw)
To: linuxppc-dev; +Cc: krafft, cbe-oss-dev
[-- Attachment #1: Type: text/plain, Size: 1710 bytes --]
From: Christian Krafft <krafft@de.ibm.com>
This patch adds a check for the private driver data to be initialized.
The bug showed up, as the caller found a pmi device by it's type.
Whereas the pmi driver probes for the type and the name.
Since the name was not as the driver expected, it did not initialize.
A more relaxed probing will be supplied with an extra patch, too.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: sdk3/arch/powerpc/sysdev/pmi.c
===================================================================
--- sdk3.orig/arch/powerpc/sysdev/pmi.c
+++ sdk3/arch/powerpc/sysdev/pmi.c
@@ -264,6 +264,9 @@ void pmi_register_handler(struct of_devi
struct pmi_data *data;
data = device->dev.driver_data;
+ if (!data)
+ return;
+
spin_lock(&data->handler_spinlock);
list_add_tail(&handler->node, &data->handler);
spin_unlock(&data->handler_spinlock);
@@ -274,10 +277,12 @@ void pmi_unregister_handler(struct of_de
struct pmi_handler *handler)
{
struct pmi_data *data;
+ data = device->dev.driver_data;
- pr_debug("pmi: unregistering handler %p\n", handler);
+ if (!data)
+ return;
- data = device->dev.driver_data;
+ pr_debug("pmi: unregistering handler %p\n", handler);
spin_lock(&data->handler_spinlock);
list_del(&handler->node);
--
Mit freundlichen Gruessen,
kind regards,
Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist
Vorsitzender des Aufsichtsrats: Johann Weihen
Geschaeftsfuehrung: Herbert Kircher
Sitz der Gesellschaft: Boeblingen
Registriergericht: Amtsgericht Stuttgart, HRB 243294
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: where is the sk_buff allocation
From: Ming Liu @ 2007-04-23 17:54 UTC (permalink / raw)
To: olof; +Cc: linuxppc-embedded
In-Reply-To: <20070423030204.GB28805@lixom.net>
Dear Olof,
Thanks for your information first.
In fact, my aim is to avoid frequent copying between socket_buffer and my
reserved memory block. So my idea is to just modify the protocal stack and
allocate the socket buffer into my reserved memory space which is also
accessible accessible for user application program, although perhaps it is
not safe to do that.
BTW, do you know in which specific file is the socket buffer allocated?
BR
Ming
>From: olof@lixom.net (Olof Johansson)
>To: Ming Liu <eemingliu@hotmail.com>
>CC: linuxppc-embedded@ozlabs.org
>Subject: Re: where is the sk_buff allocation
>Date: Sun, 22 Apr 2007 22:02:04 -0500
>
>On Sun, Apr 22, 2007 at 06:14:18PM +0000, Ming Liu wrote:
> > Dear all,
> > I am reading and understanding the Xilinx Temac device driver. I know
that
> > hard_start_xmit() is used to transmit the packets. In this function, a
> > pointer skb which points to a sk_buff needs to be passed to show the
> > location of the socket buffer. But where is that sk_buff allocation
> > sentence, and how its address (skb) is passed to the hard_start_xmit()
> > function? I want to change the address of the sk_buff in my system and
try
> > to fit this socket buffer in a pre-defined location.
>
>The sk_buff is allocated by the network stack and passed down to the
>driver. If you need the buffer to be located in a specific location
>before transmitting it, then you'll have to copy it there by hand.
>
>
>-Olof
_________________________________________________________________
享用世界上最大的电子邮件系统― MSN Hotmail。 http://www.hotmail.com
^ permalink raw reply
* Re: [PATCH] Rename MPIC_BROKEN_U3 to MPIC_U3_HT_IRQS
From: Segher Boessenkool @ 2007-04-23 17:39 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Olof Johannsson, linuxppc-dev, Paul Mackerras
In-Reply-To: <20070423084710.10570DDF14@ozlabs.org>
> Rename MPIC_BROKEN_U3 to something a little more descriptive. Its
> effect is to enable support for HT irqs behind the PCI-X/HT bridge on
> U3/U4 (aka. CPC9x5) parts.
Not quite. It's a workaround for the problem that
the U3/U4 HT interrupt interface doesn't send ACKs
for interrupts that require them ("level" interrupts).
It does this by setting the ACK bit in HT APIC config
space every time an interrupt from such a source happens.
This doesn't affect PCI bridges only.
The name change looks good though :-)
Segher
^ permalink raw reply
* Re: zImage.elf loads but does not start
From: Grant Likely @ 2007-04-23 17:35 UTC (permalink / raw)
To: Mirek23; +Cc: linuxppc-embedded
In-Reply-To: <10142161.post@talk.nabble.com>
On 4/23/07, Mirek23 <miroslaw.dach@psi.ch> wrote:
>
> I have revised the xparameters_ml403.h and the setup of the FPGA part. I have
> found that the interrupt for the RS232 was not configured. Right now I was
> able to come to the point when the kernel was uncompressed but it did not
> start:
>
> Linux/PPC load: console=ttl0,9600 ip=129.129.129.29 root=/dev/ram rw
This doesn't look right. It should be either 'console=ttyS0,<speed>'
for a full UART, or 'console=ttyUL0' for a uartlite.
BTW, serial console output is polled, not interrupt driven (but
regular serial I/O does use IRQs), so the unconfigured interrupt line
was probably not your immediate problem.
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: [PATCH 7/7] MPIC MSI backend
From: Segher Boessenkool @ 2007-04-23 17:33 UTC (permalink / raw)
To: michael; +Cc: Olof Johansson, linuxppc-dev, linux-pci, Milton Miller
In-Reply-To: <1177317115.3889.39.camel@concordia.ozlabs.ibm.com>
>>>> mpic_htmsi deals with MSIs that come in over hypertransport
>>>> to the MPIC on CPC925/CPC945; this has nothing to
>>>> do with HT APICs.
>>>
>>> Maybe it should be named mpic_cpc9x5msi instead?
>>
>> Yeah probably, esp. since there are more MSI sources
>> on those chips, not just HT; and if support for those
>> sources gets added later, it should go to this file :-)
>
> Actually I think I'll call it mpic_u3_msi.c, which although not quite
> as
> accurate as cpc9x5, is more inline with the rest of the code that
> refers
> to U3 - which really means U3/U4.
Yeah, good plan. It's a nicer name anyway :-)
Segher
^ permalink raw reply
* Re: [ofa-general] [PATCH] eHCA: Add "Modify Port" verb
From: Hal Rosenstock @ 2007-04-23 16:55 UTC (permalink / raw)
To: Joachim Fenkes; +Cc: LinuxPPC-Dev, LKML, OF-General
In-Reply-To: <200704231823.48723.fenkes@de.ibm.com>
Hi Joachim,
On Mon, 2007-04-23 at 12:23, Joachim Fenkes wrote:
> Add "Modify Port" verb support to eHCA driver.
> ib_cm needs this to initialize properly.
>
>
> Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
> ---
>
> ehca_hca.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
> hcp_if.c | 24 ++++++++++++++++++++++++
> hcp_if.h | 4 ++++
> 3 files changed, 74 insertions(+), 2 deletions(-)
>
> diff -urp a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
> --- a/drivers/infiniband/hw/ehca/ehca_hca.c 2007-02-04 19:44:54.000000000 +0100
> +++ b/drivers/infiniband/hw/ehca/ehca_hca.c 2007-04-23 18:09:38.000000000 +0200
> @@ -147,6 +147,7 @@ int ehca_query_port(struct ib_device *ib
> break;
> }
>
> + props->port_cap_flags = rblock->capability_mask;
> props->gid_tbl_len = rblock->gid_tbl_len;
> props->max_msg_sz = rblock->max_msg_sz;
> props->bad_pkey_cntr = rblock->bad_pkey_cntr;
> @@ -233,10 +234,53 @@ query_gid1:
> return ret;
> }
>
> +const u32 allowed_port_caps = (
> + IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
> + IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
> + IB_PORT_VENDOR_CLASS_SUP);
I didn't think IB_PORT_SM was allowed (as QP0 is not exposed) or does
this just fail later when it is attempted to be actually set ?
-- Hal
> +
> int ehca_modify_port(struct ib_device *ibdev,
> u8 port, int port_modify_mask,
> struct ib_port_modify *props)
> {
> - /* Not implemented yet */
> - return -EFAULT;
> + int ret = 0;
> + struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
> + struct hipz_query_port *rblock;
> + u32 cap;
> + u64 hret;
> +
> + if ((props->set_port_cap_mask | props->clr_port_cap_mask)
> + & ~allowed_port_caps) {
> + ehca_err(&shca->ib_device, "Non-changeable bits set in masks "
> + "set=%x clr=%x allowed=%x", props->set_port_cap_mask,
> + props->clr_port_cap_mask, allowed_port_caps);
> + return -EINVAL;
> + }
> +
> + rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
> + if (!rblock) {
> + ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
> + return -ENOMEM;
> + }
> +
> + if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
> + ehca_err(&shca->ib_device, "Can't query port properties");
> + ret = -EINVAL;
> + goto modify_port1;
> + }
> +
> + cap = (rblock->capability_mask | props->set_port_cap_mask)
> + & ~props->clr_port_cap_mask;
> +
> + hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
> + cap, props->init_type, port_modify_mask);
> + if (hret != H_SUCCESS) {
> + ehca_err(&shca->ib_device, "Modify port failed hret=%lx", hret);
> + ret = -EINVAL;
> + }
> +
> +modify_port1:
> + ehca_free_fw_ctrlblock(rblock);
> +
> + return ret;
> }
> diff -urp a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
> --- a/drivers/infiniband/hw/ehca/hcp_if.c 2007-02-04 19:44:54.000000000 +0100
> +++ b/drivers/infiniband/hw/ehca/hcp_if.c 2007-04-23 18:06:09.000000000 +0200
> @@ -70,6 +70,10 @@
> #define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
> #define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
>
> +#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
> +#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
> +#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
> +
> /* direct access qp controls */
> #define DAQP_CTRL_ENABLE 0x01
> #define DAQP_CTRL_SEND_COMP 0x20
> @@ -364,6 +368,26 @@ u64 hipz_h_query_port(const struct ipz_a
> return ret;
> }
>
> +u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
> + const u8 port_id, const u32 port_cap,
> + const u8 init_type, const int modify_mask)
> +{
> + u64 port_attributes = port_cap;
> +
> + if (modify_mask & IB_PORT_SHUTDOWN)
> + port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
> + if (modify_mask & IB_PORT_INIT_TYPE)
> + port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
> + if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
> + port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
> +
> + return ehca_plpar_hcall_norets(H_MODIFY_PORT,
> + adapter_handle.handle, /* r4 */
> + port_id, /* r5 */
> + port_attributes, /* r6 */
> + 0, 0, 0, 0);
> +}
> +
> u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
> struct hipz_query_hca *query_hca_rblock)
> {
> diff -urp a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
> --- a/drivers/infiniband/hw/ehca/hcp_if.h 2007-02-04 19:44:54.000000000 +0100
> +++ b/drivers/infiniband/hw/ehca/hcp_if.h 2007-04-23 18:06:09.000000000 +0200
> @@ -85,6 +85,10 @@ u64 hipz_h_query_port(const struct ipz_a
> const u8 port_id,
> struct hipz_query_port *query_port_response_block);
>
> +u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
> + const u8 port_id, const u32 port_cap,
> + const u8 init_type, const int modify_mask);
> +
> u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
> struct hipz_query_hca *query_hca_rblock);
>
>
> _______________________________________________
> general mailing list
> general@lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general
>
> To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general
^ permalink raw reply
* Re: [PATCH 1/4 v2] powerpc: document max-speed and interface-type properties
From: Andy Fleming @ 2007-04-23 16:58 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <19b21e979d2b23eba0073dadc7c65620@kernel.crashing.org>
On Apr 21, 2007, at 12:22, Segher Boessenkool wrote:
>>> Sure there's an argument for describing what type of
>>> interface the PHY is connected on, if it supports more
>>> than one -- but that should be a property in the PHY
>>> node, not the controller node, since you can have multiple
>>> PHYs connected to the same controller, possibly on
>>> different interfaces each.
>>
>> I just want to reiterate that I disagree strongly with this
>> statement. If you have multiple PHYs hooked up to one ethernet
>> controller, you're going to need to change the device tree to use
>> a different PHY, anyway. That, or have Linux ignore the phandle
>> that points to the connected PHY.
>
> On some configurations, what PHY to use is a runtime
> decision, not a static thing. No device tree change
> is necessary then.
1) Could you give me an example?
2) So you'd be having Linux ignore the phandle, then?
>> My point, again, is that the interface type is not strongly tied
>> to the PHY. It is strongly tied to the board configuration. We
>> *could* put the interface type in the PHY node, but I want to
>> disabuse you of the notion that it would be any better there.
>
> I still think it's the best place for this information.
I still disagree. :)
Andy
^ permalink raw reply
* [PATCH] eHCA: Add "Modify Port" verb
From: Joachim Fenkes @ 2007-04-23 16:23 UTC (permalink / raw)
To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
Add "Modify Port" verb support to eHCA driver.
ib_cm needs this to initialize properly.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
ehca_hca.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
hcp_if.c | 24 ++++++++++++++++++++++++
hcp_if.h | 4 ++++
3 files changed, 74 insertions(+), 2 deletions(-)
diff -urp a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
--- a/drivers/infiniband/hw/ehca/ehca_hca.c 2007-02-04 19:44:54.000000000 +0100
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c 2007-04-23 18:09:38.000000000 +0200
@@ -147,6 +147,7 @@ int ehca_query_port(struct ib_device *ib
break;
}
+ props->port_cap_flags = rblock->capability_mask;
props->gid_tbl_len = rblock->gid_tbl_len;
props->max_msg_sz = rblock->max_msg_sz;
props->bad_pkey_cntr = rblock->bad_pkey_cntr;
@@ -233,10 +234,53 @@ query_gid1:
return ret;
}
+const u32 allowed_port_caps = (
+ IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
+ IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
+ IB_PORT_VENDOR_CLASS_SUP);
+
int ehca_modify_port(struct ib_device *ibdev,
u8 port, int port_modify_mask,
struct ib_port_modify *props)
{
- /* Not implemented yet */
- return -EFAULT;
+ int ret = 0;
+ struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
+ struct hipz_query_port *rblock;
+ u32 cap;
+ u64 hret;
+
+ if ((props->set_port_cap_mask | props->clr_port_cap_mask)
+ & ~allowed_port_caps) {
+ ehca_err(&shca->ib_device, "Non-changeable bits set in masks "
+ "set=%x clr=%x allowed=%x", props->set_port_cap_mask,
+ props->clr_port_cap_mask, allowed_port_caps);
+ return -EINVAL;
+ }
+
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!rblock) {
+ ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+ return -ENOMEM;
+ }
+
+ if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+ ehca_err(&shca->ib_device, "Can't query port properties");
+ ret = -EINVAL;
+ goto modify_port1;
+ }
+
+ cap = (rblock->capability_mask | props->set_port_cap_mask)
+ & ~props->clr_port_cap_mask;
+
+ hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
+ cap, props->init_type, port_modify_mask);
+ if (hret != H_SUCCESS) {
+ ehca_err(&shca->ib_device, "Modify port failed hret=%lx", hret);
+ ret = -EINVAL;
+ }
+
+modify_port1:
+ ehca_free_fw_ctrlblock(rblock);
+
+ return ret;
}
diff -urp a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
--- a/drivers/infiniband/hw/ehca/hcp_if.c 2007-02-04 19:44:54.000000000 +0100
+++ b/drivers/infiniband/hw/ehca/hcp_if.c 2007-04-23 18:06:09.000000000 +0200
@@ -70,6 +70,10 @@
#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31)
#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63)
+#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47)
+#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
+#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
+
/* direct access qp controls */
#define DAQP_CTRL_ENABLE 0x01
#define DAQP_CTRL_SEND_COMP 0x20
@@ -364,6 +368,26 @@ u64 hipz_h_query_port(const struct ipz_a
return ret;
}
+u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
+ const u8 port_id, const u32 port_cap,
+ const u8 init_type, const int modify_mask)
+{
+ u64 port_attributes = port_cap;
+
+ if (modify_mask & IB_PORT_SHUTDOWN)
+ port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
+ if (modify_mask & IB_PORT_INIT_TYPE)
+ port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
+ if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
+ port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
+
+ return ehca_plpar_hcall_norets(H_MODIFY_PORT,
+ adapter_handle.handle, /* r4 */
+ port_id, /* r5 */
+ port_attributes, /* r6 */
+ 0, 0, 0, 0);
+}
+
u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
struct hipz_query_hca *query_hca_rblock)
{
diff -urp a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
--- a/drivers/infiniband/hw/ehca/hcp_if.h 2007-02-04 19:44:54.000000000 +0100
+++ b/drivers/infiniband/hw/ehca/hcp_if.h 2007-04-23 18:06:09.000000000 +0200
@@ -85,6 +85,10 @@ u64 hipz_h_query_port(const struct ipz_a
const u8 port_id,
struct hipz_query_port *query_port_response_block);
+u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
+ const u8 port_id, const u32 port_cap,
+ const u8 init_type, const int modify_mask);
+
u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
struct hipz_query_hca *query_hca_rblock);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox