* [PATCH 01/10] IB/ehca: Support for multiple event queues
From: Joachim Fenkes @ 2007-07-12 15:46 UTC (permalink / raw)
To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707121745.27592.fenkes@de.ibm.com>
From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
The eHCA driver can now handle multiple event queues (read: interrupt
sources) instead of one. The number of available EQs is selected via the
nr_eqs module parameter.
CQs are either assigned to the EQs based on the comp_vector index or, if the
dist_eqs module parameter is supplied, using a round-robin scheme.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_classes.h | 13 +++-
drivers/infiniband/hw/ehca/ehca_cq.c | 16 +++-
drivers/infiniband/hw/ehca/ehca_eq.c | 139 ++++++++++++++++++-----------
drivers/infiniband/hw/ehca/ehca_irq.c | 36 +++-----
drivers/infiniband/hw/ehca/ehca_irq.h | 8 +-
drivers/infiniband/hw/ehca/ehca_iverbs.h | 9 +-
drivers/infiniband/hw/ehca/ehca_main.c | 118 ++++++++++++++++++++-----
drivers/infiniband/hw/ehca/ehca_qp.c | 2 +-
8 files changed, 233 insertions(+), 108 deletions(-)
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index daf823e..b2d614a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -72,7 +72,11 @@ struct ehca_eqe_cache_entry {
struct ehca_cq *cq;
};
+struct ehca_shca;
+
struct ehca_eq {
+ struct ehca_shca *shca;
+ char name[17];
u32 length;
struct ipz_queue ipz_queue;
struct ipz_eq_handle ipz_eq_handle;
@@ -100,6 +104,7 @@ struct ehca_sport {
struct ehca_sma_attr saved_attr;
};
+#define EHCA_MAX_NR_EQS 512
struct ehca_shca {
struct ib_device ib_device;
struct ibmebus_dev *ibmebus_dev;
@@ -108,14 +113,16 @@ struct ehca_shca {
struct list_head shca_list;
struct ipz_adapter_handle ipz_hca_handle;
struct ehca_sport sport[2];
- struct ehca_eq eq;
- struct ehca_eq neq;
+ struct ehca_eq **eqs;
+ struct ehca_eq *aeq; /* async event for qps */
+ struct ehca_eq *neq;
struct ehca_mr *maxmr;
struct ehca_pd *pd;
struct h_galpas galpas;
struct mutex modify_mutex;
u64 hca_cap;
int max_mtu;
+ atomic_t cur_eq_idx;
};
struct ehca_pd {
@@ -290,6 +297,8 @@ struct ehca_ucontext {
int ehca_init_pd_cache(void);
void ehca_cleanup_pd_cache(void);
+int ehca_init_eq_cache(void);
+void ehca_cleanup_eq_cache(void);
int ehca_init_cq_cache(void);
void ehca_cleanup_cq_cache(void);
int ehca_init_qp_cache(void);
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 01d4a14..97da51e 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -117,6 +117,8 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
struct ib_ucontext *context,
struct ib_udata *udata)
{
+ extern int ehca_nr_eqs;
+ extern int ehca_dist_eqs;
static const u32 additional_cqe = 20;
struct ib_cq *cq;
struct ehca_cq *my_cq;
@@ -134,6 +136,12 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL);
+ if (comp_vector < 0 || comp_vector >= ehca_nr_eqs) {
+ ehca_err(device, "Invalid comp_vector=%x ehca_nr_eqs=%x",
+ comp_vector, ehca_nr_eqs);
+ return ERR_PTR(-EINVAL);
+ }
+
my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
if (!my_cq) {
ehca_err(device, "Out of memory for ehca_cq struct device=%p",
@@ -153,7 +161,13 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
cq = &my_cq->ib_cq;
adapter_handle = shca->ipz_hca_handle;
- param.eq_handle = shca->eq.ipz_eq_handle;
+ if (!ehca_dist_eqs)
+ param.eq_handle = shca->eqs[comp_vector]->ipz_eq_handle;
+ else {
+ u32 eq_idx = atomic_inc_return(&shca->cur_eq_idx) % ehca_nr_eqs;
+ param.eq_handle = shca->eqs[eq_idx]->ipz_eq_handle;
+ ehca_dbg(device, "assigned comp_vector=%x", eq_idx);
+ }
do {
if (!idr_pre_get(&ehca_cq_idr, GFP_KERNEL)) {
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 4961eb8..d443bcb 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -8,6 +8,7 @@
* Reinhard Ernst <rernst@de.ibm.com>
* Heiko J Schick <schickhj@de.ibm.com>
* Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ * Joachim Fenkes <fenkes@de.ibm.com>
*
*
* Copyright (c) 2005 IBM Corporation
@@ -50,40 +51,54 @@
#include "hcp_if.h"
#include "ipz_pt_fn.h"
-int ehca_create_eq(struct ehca_shca *shca,
- struct ehca_eq *eq,
- const enum ehca_eq_type type, const u32 length)
+static struct kmem_cache *eq_cache;
+
+struct ehca_eq *ehca_create_eq(struct ehca_shca *shca,
+ const enum ehca_eq_type type, const u32 length)
{
- u64 ret;
+ struct ehca_eq *eq = NULL;
+ int ret;
+ u64 h_ret;
u32 nr_pages;
u32 i;
void *vpage;
struct ib_device *ib_dev = &shca->ib_device;
- spin_lock_init(&eq->spinlock);
- spin_lock_init(&eq->irq_spinlock);
- eq->is_initialized = 0;
+ if (!length) {
+ ehca_err(ib_dev, "EQ length must not be zero.");
+ return ERR_PTR(-EINVAL);
+ }
if (type != EHCA_EQ && type != EHCA_NEQ) {
- ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq);
- return -EINVAL;
+ ehca_err(ib_dev, "Invalid EQ type %x", type);
+ return ERR_PTR(-EINVAL);
}
- if (!length) {
- ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq);
- return -EINVAL;
+
+ eq = kmem_cache_zalloc(eq_cache, GFP_KERNEL);
+ if (!eq) {
+ ehca_err(ib_dev, "Out of memory for ehca_eq struct device=%p",
+ ib_dev);
+ return ERR_PTR(-ENOMEM);
}
- ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
- &eq->pf,
- type,
- length,
- &eq->ipz_eq_handle,
- &eq->length,
- &nr_pages, &eq->ist);
+ spin_lock_init(&eq->spinlock);
+ spin_lock_init(&eq->irq_spinlock);
+ eq->is_initialized = 0;
+ eq->shca = shca;
- if (ret != H_SUCCESS) {
- ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
- return -EINVAL;
+ h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
+ &eq->pf,
+ type,
+ length,
+ &eq->ipz_eq_handle,
+ &eq->length,
+ &nr_pages, &eq->ist);
+
+ if (h_ret != H_SUCCESS) {
+ ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p h_ret=%lx",
+ eq, h_ret);
+ ret = -EINVAL;
+ goto create_eq_exit0;
}
ret = ipz_queue_ctor(&eq->ipz_queue, nr_pages,
@@ -97,51 +112,51 @@ int ehca_create_eq(struct ehca_shca *shca,
u64 rpage;
if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) {
- ret = H_RESOURCE;
+ ret = -ENOMEM;
goto create_eq_exit2;
}
rpage = virt_to_abs(vpage);
- ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
- eq->ipz_eq_handle,
- &eq->pf,
- 0, 0, rpage, 1);
+ h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
+ eq->ipz_eq_handle,
+ &eq->pf,
+ 0, 0, rpage, 1);
if (i == (nr_pages - 1)) {
/* last page */
vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
- if (ret != H_SUCCESS || vpage)
+ if (h_ret != H_SUCCESS || vpage) {
+ ret = -ENOMEM;
goto create_eq_exit2;
+ }
} else {
- if (ret != H_PAGE_REGISTERED || !vpage)
+ if (h_ret != H_PAGE_REGISTERED || !vpage) {
+ ret = -ENOMEM;
goto create_eq_exit2;
+ }
}
}
ipz_qeit_reset(&eq->ipz_queue);
/* register interrupt handlers and initialize work queues */
- if (type == EHCA_EQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
- IRQF_DISABLED, "ehca_eq",
- (void *)shca);
- if (ret < 0)
- ehca_err(ib_dev, "Can't map interrupt handler.");
-
- tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
- } else if (type == EHCA_NEQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
- IRQF_DISABLED, "ehca_neq",
- (void *)shca);
- if (ret < 0)
- ehca_err(ib_dev, "Can't map interrupt handler.");
-
- tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
- }
+ if (type == EHCA_EQ)
+ snprintf(eq->name, sizeof(eq->name), "ehca_eq_%x", eq->ist);
+ else
+ snprintf(eq->name, sizeof(eq->name), "ehca_neq");
+
+ ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt,
+ IRQF_DISABLED, eq->name, (void *)eq);
+ if (ret < 0)
+ ehca_err(ib_dev, "Can't map interrupt handler.");
+
+ tasklet_init(&eq->interrupt_task,
+ (type == EHCA_EQ) ? ehca_tasklet_eq : ehca_tasklet_neq,
+ (long)eq);
eq->is_initialized = 1;
- return 0;
+ return eq;
create_eq_exit2:
ipz_queue_dtor(&eq->ipz_queue);
@@ -149,10 +164,13 @@ create_eq_exit2:
create_eq_exit1:
hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
- return -EINVAL;
+create_eq_exit0:
+ kmem_cache_free(eq_cache, eq);
+
+ return ERR_PTR(ret);
}
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+void *ehca_poll_eq(struct ehca_eq *eq)
{
unsigned long flags;
void *eqe;
@@ -164,13 +182,14 @@ void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
return eqe;
}
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+int ehca_destroy_eq(struct ehca_eq *eq)
{
+ struct ehca_shca *shca = eq->shca;
unsigned long flags;
u64 h_ret;
spin_lock_irqsave(&eq->spinlock, flags);
- ibmebus_free_irq(NULL, eq->ist, (void *)shca);
+ ibmebus_free_irq(NULL, eq->ist, (void *)eq);
h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
@@ -181,6 +200,24 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
return -EINVAL;
}
ipz_queue_dtor(&eq->ipz_queue);
+ kmem_cache_free(eq_cache, eq);
return 0;
}
+
+int ehca_init_eq_cache(void)
+{
+ eq_cache = kmem_cache_create("ehca_cache_eq",
+ sizeof(struct ehca_eq), 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!eq_cache)
+ return -ENOMEM;
+ return 0;
+}
+
+void ehca_cleanup_eq_cache(void)
+{
+ if (eq_cache)
+ kmem_cache_destroy(eq_cache);
+}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 96eba38..7a4071a 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -389,32 +389,24 @@ static inline void reset_eq_pending(struct ehca_cq *cq)
return;
}
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id)
-{
- struct ehca_shca *shca = (struct ehca_shca*)dev_id;
-
- tasklet_hi_schedule(&shca->neq.interrupt_task);
-
- return IRQ_HANDLED;
-}
-
void ehca_tasklet_neq(unsigned long data)
{
- struct ehca_shca *shca = (struct ehca_shca*)data;
+ struct ehca_eq *neq = (struct ehca_eq *)data;
+ struct ehca_shca *shca = neq->shca;
struct ehca_eqe *eqe;
u64 ret;
- eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+ eqe = (struct ehca_eqe *)ehca_poll_eq(neq);
while (eqe) {
if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry))
parse_ec(shca, eqe->entry);
- eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+ eqe = (struct ehca_eqe *)ehca_poll_eq(neq);
}
ret = hipz_h_reset_event(shca->ipz_hca_handle,
- shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
+ neq->ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
if (ret != H_SUCCESS)
ehca_err(&shca->ib_device, "Can't clear notification events.");
@@ -422,11 +414,11 @@ void ehca_tasklet_neq(unsigned long data)
return;
}
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
+irqreturn_t ehca_interrupt(int irq, void *dev_id)
{
- struct ehca_shca *shca = (struct ehca_shca*)dev_id;
+ struct ehca_eq *eq = (struct ehca_eq *)dev_id;
- tasklet_hi_schedule(&shca->eq.interrupt_task);
+ tasklet_hi_schedule(&eq->interrupt_task);
return IRQ_HANDLED;
}
@@ -468,9 +460,9 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
}
}
-void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+void ehca_process_eq(struct ehca_eq *eq, int is_irq)
{
- struct ehca_eq *eq = &shca->eq;
+ struct ehca_shca *shca = eq->shca;
struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
u64 eqe_value;
unsigned long flags;
@@ -498,7 +490,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
do {
u32 token;
eqe_cache[eqe_cnt].eqe =
- (struct ehca_eqe *)ehca_poll_eq(shca, eq);
+ (struct ehca_eqe *)ehca_poll_eq(eq);
if (!eqe_cache[eqe_cnt].eqe)
break;
eqe_value = eqe_cache[eqe_cnt].eqe->entry;
@@ -535,7 +527,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
}
/* check eq */
spin_lock(&eq->spinlock);
- eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+ eq_empty = (!ipz_eqit_eq_peek_valid(&eq->ipz_queue));
spin_unlock(&eq->spinlock);
/* call completion handler for cached eqes */
for (i = 0; i < eqe_cnt; i++)
@@ -557,7 +549,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
goto unlock_irq_spinlock;
do {
struct ehca_eqe *eqe;
- eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+ eqe = (struct ehca_eqe *)ehca_poll_eq(eq);
if (!eqe)
break;
process_eqe(shca, eqe);
@@ -569,7 +561,7 @@ unlock_irq_spinlock:
void ehca_tasklet_eq(unsigned long data)
{
- ehca_process_eq((struct ehca_shca*)data, 1);
+ ehca_process_eq((struct ehca_eq *)data, 1);
}
static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 3346cb0..18d5397 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -50,12 +50,10 @@ struct ehca_shca;
int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id);
-void ehca_tasklet_neq(unsigned long data);
-
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
+irqreturn_t ehca_interrupt(int irq, void *dev_id);
void ehca_tasklet_eq(unsigned long data);
-void ehca_process_eq(struct ehca_shca *shca, int is_irq);
+void ehca_tasklet_neq(unsigned long data);
+void ehca_process_eq(struct ehca_eq *eq, int is_irq);
struct ehca_cpu_comp_task {
wait_queue_head_t wait_queue;
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 77aeca6..bf8fbf7 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -117,13 +117,12 @@ enum ehca_eq_type {
EHCA_NEQ /* Notification Event Queue */
};
-int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq,
- enum ehca_eq_type type, const u32 length);
+struct ehca_eq *ehca_create_eq(struct ehca_shca *shca,
+ const enum ehca_eq_type type, const u32 length);
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
-
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
+int ehca_destroy_eq(struct ehca_eq *eq);
+void *ehca_poll_eq(struct ehca_eq *eq);
struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
struct ib_ucontext *context,
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 28ba2dd..d9a37dc 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -63,6 +63,8 @@ int ehca_port_act_time = 30;
int ehca_poll_all_eqs = 1;
int ehca_static_rate = -1;
int ehca_scaling_code = 0;
+int ehca_nr_eqs = 2;
+int ehca_dist_eqs = 0;
module_param_named(open_aqp1, ehca_open_aqp1, int, 0);
module_param_named(debug_level, ehca_debug_level, int, 0);
@@ -72,7 +74,9 @@ module_param_named(use_hp_mr, ehca_use_hp_mr, int, 0);
module_param_named(port_act_time, ehca_port_act_time, int, 0);
module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, 0);
module_param_named(static_rate, ehca_static_rate, int, 0);
-module_param_named(scaling_code, ehca_scaling_code, int, 0);
+module_param_named(scaling_code, ehca_scaling_code, int, 0);
+module_param_named(nr_eqs, ehca_nr_eqs, int, 0);
+module_param_named(dist_eqs, ehca_dist_eqs, int, 0);
MODULE_PARM_DESC(open_aqp1,
"AQP1 on startup (0: no (default), 1: yes)");
@@ -95,6 +99,11 @@ MODULE_PARM_DESC(static_rate,
"set permanent static rate (default: disabled)");
MODULE_PARM_DESC(scaling_code,
"set scaling code (0: disabled/default, 1: enabled)");
+MODULE_PARM_DESC(nr_eqs,
+ "set number of event queues (default : 2)");
+MODULE_PARM_DESC(dist_eqs,
+ "enable distributing EQs across CQs "
+ "(0: disabled/default, 1: enabled)");
DEFINE_RWLOCK(ehca_qp_idr_lock);
DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -135,6 +144,12 @@ static int ehca_create_slab_caches(void)
return ret;
}
+ ret = ehca_init_eq_cache();
+ if (ret) {
+ ehca_gen_err("Cannot create EQ SLAB cache.");
+ goto create_slab_caches1;
+ }
+
ret = ehca_init_cq_cache();
if (ret) {
ehca_gen_err("Cannot create CQ SLAB cache.");
@@ -182,6 +197,9 @@ create_slab_caches3:
ehca_cleanup_cq_cache();
create_slab_caches2:
+ ehca_cleanup_eq_cache();
+
+create_slab_caches1:
ehca_cleanup_pd_cache();
return ret;
@@ -193,6 +211,7 @@ static void ehca_destroy_slab_caches(void)
ehca_cleanup_av_cache();
ehca_cleanup_qp_cache();
ehca_cleanup_cq_cache();
+ ehca_cleanup_eq_cache();
ehca_cleanup_pd_cache();
#ifdef CONFIG_PPC_64K_PAGES
if (ctblk_cache)
@@ -362,7 +381,7 @@ int ehca_init_device(struct ehca_shca *shca)
shca->ib_device.node_type = RDMA_NODE_IB_CA;
shca->ib_device.phys_port_cnt = shca->num_ports;
- shca->ib_device.num_comp_vectors = 1;
+ shca->ib_device.num_comp_vectors = ehca_nr_eqs;
shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev;
shca->ib_device.query_device = ehca_query_device;
shca->ib_device.query_port = ehca_query_port;
@@ -585,6 +604,15 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
}
static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
+static ssize_t ehca_show_nr_eqs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", ehca_nr_eqs);
+}
+
+static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);
+
static struct attribute *ehca_dev_attrs[] = {
&dev_attr_adapter_handle.attr,
&dev_attr_num_ports.attr,
@@ -601,6 +629,7 @@ static struct attribute *ehca_dev_attrs[] = {
&dev_attr_cur_mw.attr,
&dev_attr_max_pd.attr,
&dev_attr_max_ah.attr,
+ &dev_attr_nr_eqs.attr,
NULL
};
@@ -608,13 +637,27 @@ static struct attribute_group ehca_dev_attr_grp = {
.attrs = ehca_dev_attrs
};
+static void destroy_all_eqs(struct ehca_shca *shca)
+{
+ int ret, i;
+
+ for (i = 0; i < ehca_nr_eqs && shca->eqs[i]; i++) {
+ ret = ehca_destroy_eq(shca->eqs[i]);
+ if (ret)
+ ehca_err(&shca->ib_device, "Cannot destroy EQ "
+ "ret=%x i=%x eq=%p", ret, i, shca->eqs[i]);
+ }
+
+ kfree(shca->eqs);
+}
+
static int __devinit ehca_probe(struct ibmebus_dev *dev,
const struct of_device_id *id)
{
struct ehca_shca *shca;
const u64 *handle;
struct ib_pd *ibpd;
- int ret;
+ int ret, i;
handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
if (!handle) {
@@ -648,19 +691,35 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
ret = ehca_init_device(shca);
if (ret) {
- ehca_gen_err("Cannot init ehca device struct");
+ ehca_gen_err("Cannot init ehca device struct");
goto probe1;
}
/* create event queues */
- ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
- if (ret) {
- ehca_err(&shca->ib_device, "Cannot create EQ.");
+ shca->eqs = kzalloc(ehca_nr_eqs * sizeof(*shca->eqs), GFP_KERNEL);
+ if (!shca->eqs) {
+ ehca_gen_err("Cannot alloc eqs array");
goto probe1;
}
- ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
- if (ret) {
+ for (i = 0; i < ehca_nr_eqs; i++) {
+ shca->eqs[i] = ehca_create_eq(shca, EHCA_EQ, 2048);
+ if (IS_ERR(shca->eqs[i])) {
+ ehca_err(&shca->ib_device, "Cannot create EQ.");
+ ret = PTR_ERR(shca->eqs[i]);
+ shca->eqs[i] = NULL;
+ goto probe2;
+ }
+ }
+
+ shca->aeq = ehca_create_eq(shca, EHCA_EQ, 2048);
+ if (IS_ERR(shca->aeq)) {
+ ehca_err(&shca->ib_device, "Cannot create AEQ.");
+ goto probe2;
+ }
+
+ shca->neq = ehca_create_eq(shca, EHCA_NEQ, 513);
+ if (IS_ERR(shca->neq)) {
ehca_err(&shca->ib_device, "Cannot create NEQ.");
goto probe3;
}
@@ -747,16 +806,20 @@ probe5:
"Cannot destroy internal PD. ret=%x", ret);
probe4:
- ret = ehca_destroy_eq(shca, &shca->neq);
+ ret = ehca_destroy_eq(shca->neq);
if (ret)
ehca_err(&shca->ib_device,
"Cannot destroy NEQ. ret=%x", ret);
probe3:
- ret = ehca_destroy_eq(shca, &shca->eq);
+ ret = ehca_destroy_eq(shca->aeq);
if (ret)
ehca_err(&shca->ib_device,
- "Cannot destroy EQ. ret=%x", ret);
+ "Cannot destroy AEQ. ret=%x", ret);
+
+probe2:
+ if (shca->eqs)
+ destroy_all_eqs(shca);
probe1:
ib_dealloc_device(&shca->ib_device);
@@ -767,12 +830,11 @@ probe1:
static int __devexit ehca_remove(struct ibmebus_dev *dev)
{
struct ehca_shca *shca = dev->ofdev.dev.driver_data;
- int ret;
+ int ret, i;
sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
if (ehca_open_aqp1 == 1) {
- int i;
for (i = 0; i < shca->num_ports; i++) {
ret = ehca_destroy_aqp1(&shca->sport[i]);
if (ret)
@@ -794,11 +856,14 @@ static int __devexit ehca_remove(struct ibmebus_dev *dev)
ehca_err(&shca->ib_device,
"Cannot destroy internal PD. ret=%x", ret);
- ret = ehca_destroy_eq(shca, &shca->eq);
+ if (shca->eqs)
+ destroy_all_eqs(shca);
+
+ ret = ehca_destroy_eq(shca->aeq);
if (ret)
- ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%x", ret);
+ ehca_err(&shca->ib_device, "Canot destroy AEQ. ret=%x", ret);
- ret = ehca_destroy_eq(shca, &shca->neq);
+ ret = ehca_destroy_eq(shca->neq);
if (ret)
ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%x", ret);
@@ -829,16 +894,20 @@ static struct ibmebus_driver ehca_driver = {
void ehca_poll_eqs(unsigned long data)
{
+ extern int ehca_nr_eqs;
struct ehca_shca *shca;
spin_lock(&shca_list_lock);
list_for_each_entry(shca, &shca_list, shca_list) {
- if (shca->eq.is_initialized) {
- /* call deadman proc only if eq ptr does not change */
- struct ehca_eq *eq = &shca->eq;
+ int i;
+ for (i = 0; i < ehca_nr_eqs; i++) {
+ struct ehca_eq *eq = shca->eqs[i];
int max = 3;
volatile u64 q_ofs, q_ofs2;
u64 flags;
+ if (!eq || !eq->is_initialized)
+ continue;
+ /* call deadman proc only if eq ptr does not change */
spin_lock_irqsave(&eq->spinlock, flags);
q_ofs = eq->ipz_queue.current_q_offset;
spin_unlock_irqrestore(&eq->spinlock, flags);
@@ -849,7 +918,7 @@ void ehca_poll_eqs(unsigned long data)
max--;
} while (q_ofs == q_ofs2 && max > 0);
if (q_ofs == q_ofs2)
- ehca_process_eq(shca, 0);
+ ehca_process_eq(eq, 0);
}
}
mod_timer(&poll_eqs_timer, jiffies + HZ);
@@ -863,6 +932,13 @@ int __init ehca_module_init(void)
printk(KERN_INFO "eHCA Infiniband Device Driver "
"(Rel.: SVNEHCA_0023)\n");
+ if (ehca_nr_eqs < 1 || ehca_nr_eqs > EHCA_MAX_NR_EQS) {
+ ehca_gen_err("Invalid option nr_eqs=%x. "
+ "Specify a number in range [1-%d].",
+ ehca_nr_eqs, EHCA_MAX_NR_EQS);
+ return -EINVAL;
+ }
+
if ((ret = ehca_create_comp_pool())) {
ehca_gen_err("Cannot create comp pool.");
return ret;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 7467125..f6f4ef6 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -545,7 +545,7 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
}
parms.token = my_qp->token;
- parms.eq_handle = shca->eq.ipz_eq_handle;
+ parms.eq_handle = shca->aeq->ipz_eq_handle;
parms.pd = my_pd->fw_pd;
if (my_qp->send_cq)
parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
--
1.5.2
^ permalink raw reply related
* [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes
From: Joachim Fenkes @ 2007-07-12 15:45 UTC (permalink / raw)
To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
Cc: Stefan Roscher, Christoph Raisch
Building on top of the last patch series, this set of patches adds multi-EQ
support, fixes a few nits (including formatting), refactors the MR/MW code
and adds support for large page MRs. Another patch set will follow.
Note that patch 7 will introduce a few lines over 80 chars that will be
unindented in patch 8 - I hope that's okay with you.
The patches, in detail, are:
[01/10] adds support for multiple event queues (ie interrupt sources)
[02/10] fixes a problem with HW autodetection
[03/10] \
[04/10] |
[05/10] | These refactor and clean up the MR/MW code. We split them into
[06/10] | bite-sized chunks for easier review of the changes.
[07/10] |=20
[08/10] /=20
[09/10] fixes a lot of checkpatch.pl warnings
[10/10] adds large page MR support for eHCA2
The patches should apply cleanly, in order, against Roland's git. Please
review the changes and apply the patches if they are okay.
Regards,
Joachim
=2D-=20
Joachim Fenkes =A0-- =A0eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH =A0-- =A0Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220 =A0-- =A071032 Boeblingen =A0-- =A0Germany
eMail: fenkes@de.ibm.com
^ permalink raw reply
* RE: [PATCH 1/2] Kernel: Move all technical descriptons of the DeviceTree Complier
From: Yoder Stuart-B08248 @ 2007-07-12 15:25 UTC (permalink / raw)
To: Paul Mackerras, Loeliger Jon-LOELIGER; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <18069.41758.420516.135000@cargo.ozlabs.ibm.com>
=20
> -----Original Message-----
> From: linuxppc-dev-bounces+b08248=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-dev-bounces+b08248=3Dfreescale.com@ozlabs.org]=20
> On Behalf Of Paul Mackerras
> Sent: Wednesday, July 11, 2007 10:42 PM
> To: Loeliger Jon-LOELIGER
> Cc: linuxppc-dev@ozlabs.org; Jon Loeliger
> Subject: Re: [PATCH 1/2] Kernel: Move all technical=20
> descriptons of the DeviceTree Complier
>=20
> Jon Loeliger writes:
>=20
> > and its formats, command lines, descriptions, etc,
> > over to the Device Tree Compiler repositories now.
>=20
> Hrm, section II (DT block format) is a description of a kernel
> interface, and I think it should stay. After all, there's nothing
> that says that you have to use dtc to generate the device tree blob,
> so there is no reason for the dtc source to be the only place where
> the format is specified.
>=20
> I have no problem with that section being copied over to the dtc
> source.
I think creating copies is going to cause problems as now there will
be two document to be kept in sync.
What's wrong with simply putting a pointer/link in b-w-o.txt to the
DTC source repository and stating the the Linux kernel implements=20
version x.y of the DTC binary blob standard.
After all, many standards may be used by the kernel (e.g. ELF) without
the
standard document itself being kept/mainatined in the kernel source
tree.
The DTB format down the road may be used by hypervisors (e.g. Xen) and
OSes other than Linux, and thus it makes to keep it independent of the
kernel.
Stuart
^ permalink raw reply
* Re: [PATCH] do firmware feature fixups after features are initialised
From: Michael Neuling @ 2007-07-12 15:15 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: paulus, linuxppc-dev
In-Reply-To: <200707121136.49170.arnd@arndb.de>
> > > If I'm understanding this right, the first solution should be something
> > > along the lines of the patch below (not tested), which even removes
> > > more lines than it adds. It doesn't seem that annoying to me, and it
> > > makes sense to assume that the fw_features are set up after returning
> > > from the ppc_md probe.
> >
> > I'm not sure this patch is going to work as the do_feature_fixups isn't
> > called any earlier?
>
> Right, my patch still assumes that yours gets removed.
Arrh, cool.. that would better :-)
Mikey
^ permalink raw reply
* RE: [RFC][PATCH 6/8] Walnut DTS
From: Yoder Stuart-B08248 @ 2007-07-12 15:13 UTC (permalink / raw)
To: Segher Boessenkool, Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <4EAC985A-2F04-465D-AB69-C67807310D7B@kernel.crashing.org>
=20
> -----Original Message-----
> From: linuxppc-dev-bounces+b08248=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-dev-bounces+b08248=3Dfreescale.com@ozlabs.org]=20
> On Behalf Of Segher Boessenkool
> Sent: Wednesday, July 11, 2007 12:50 PM
> To: Josh Boyer
> Cc: linuxppc-dev@ozlabs.org
> Subject: Re: [RFC][PATCH 6/8] Walnut DTS
>=20
> > + UIC0: interrupt-controller0 {
>=20
> Why not just "interrupt-controller"?
>=20
> > + #address-cells =3D <0>;
> > + #size-cells =3D <0>;
>=20
> No need for these.
Isn't a good practice to put #address-cells in interrupt controller
nodes?
If the device tree has an interrupt map defined the interrupt
parent 'unit interrupt specifier' has to be interpreted according
to the #address-cells of the interrupt parent. It seems like=20
typical practice in the current DTS files to explicitly define this
in the interrupt controller.
Of course this particular device tree doesn't have an interrupt
map...
#size-cells is not needed.
Stuart
^ permalink raw reply
* Re: [Cbe-oss-dev] PS3 improved video mode autodetection for HDMI/DVI
From: Geert Uytterhoeven @ 2007-07-12 15:12 UTC (permalink / raw)
To: Håvard Espeland
Cc: Linux/PPC Development, Cell Broadband Engine OSS Development,
Ben Collins
In-Reply-To: <20070712140620.GB507@ping.uio.no>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: TEXT/PLAIN; charset=UTF-8, Size: 3426 bytes --]
On Thu, 12 Jul 2007, [iso-8859-1] Håvard Espeland wrote:
> On Thu, Jul 12, 2007 at 10:40:47AM +0200, Geert Uytterhoeven wrote:
> > If it fails, please add `#define DEBUG' to drivers/ps3/ps3av.c, send me the
> > `Monitor Info' output in the kernel log (dmesg), and tell me which of the
> > PS3 video modes (1-13) work and which don't. ps3av has a quirk database for
> > monitors that advertise non-working modes, so it can probably be fixed.
> > (BTW, even if autodetect works fine, I always welcome this information)
> >
> > In case you have a big pile of monitors at your site, you don't have to reboot
> > to try them all. Just plug in the new monitor and run `ps3videomode -v 0' to
> > switch to the best resolution of the newly-connected monitor.
>
> Hi, the autodetect code does not work correctly with a LG L226WTQ
> (native resolution 1680x1050). The detected mode (11) works fine without
> fullscreen, but goes out of range with '-f'.
This `supported resolution 11' is not the same as the mode number to pass to
ps3videomode, it's a PS3AV_CMD_VIDEO_VID_* ID.
Vid 11 corresponds to PS3AV_CMD_VIDEO_VID_1080P_60Hz (i.e. 1080p).
While mode 11 is WXGA (i.e. 1280x768).
(Upon further inspection, this `vid' is immediately converted to a mode number,
so I'll change the code to use mode numbers instead, and cause less
confusion).
> Resolutions w/o fullscreen:
> OK: 2, 3, 7, 8, 11, 12
> BAD: 1, 4, 5, 6, 9, 10, 13
Looks reasonable for a 1680x1050 monitor...
> Resolutions with fullscreen:
> OK: 2, 3, 7, 8
> BAD: 1, 4, 5, 6, 9, 10, 11, 12, 13
Euh, `-f' shouldn't make any difference for modes 11-13, as they're always
fullscreen.
> Monitor Info: size 96
> avport: 00
> monitor_id: 1e 6d 4e 56 d7 2a 03 00 03 11
> monitor_type: 02
> monitor_name: L226WTQ
> resolution_60: bits: 0000400d native: 00000000
> resolution_50: bits: 00000000 native: 00000000
> resolution_other: bits: 00000000 native: 00000000
> resolution_vesa: bits: 00000001 native: 00000000
So your monitor advertises:
Supported 60 Hz modes: 1080p 480p 720p 1080i (0000400d)
Supported VESA modes: VGA (00000001)
But 1080p and 1080i don't work. As 1080p is the best advertised mode, you don't
get anything to see :-(
Does this patch help? It should give you 720p by default.
Index: ps3-linux-2.6/drivers/ps3/ps3av.c
===================================================================
--- ps3-linux-2.6.orig/drivers/ps3/ps3av.c 2007-07-12 10:26:33.000000000 +0200
+++ ps3-linux-2.6/drivers/ps3/ps3av.c 2007-07-12 16:57:39.000000000 +0200
@@ -720,6 +720,10 @@ static const struct ps3av_monitor_quirk
{
.monitor_name = "DELL 2007WFP",
.clear_60 = PS3AV_RESBIT_1920x1080I
+ }, {
+ .monitor_name = "L226WTQ",
+ .clear_60 = PS3AV_RESBIT_1920x1080I |
+ PS3AV_RESBIT_1920x1080P
}
};
Thanks a lot for your report!
With kind regards,
Geert Uytterhoeven
Software Architect
Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/
Sony Network and Software Technology Center Europe
A division of Sony Service Centre (Europe) N.V.
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium
VAT BE 0413.825.160 · RPR Brussels
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619
^ permalink raw reply
* Re: [PATCH] [POWERPC] Move generic MPC82xx functions out of ADS-specific
From: Laurent Pinchart @ 2007-07-12 15:07 UTC (permalink / raw)
To: Scott Wood; +Cc: Vitaly Bordug, linuxppc-embedded
In-Reply-To: <4694F66D.2010907@freescale.com>
Hi Scott,
On Wednesday 11 July 2007 17:25, Scott Wood wrote:
> Laurent Pinchart wrote:
> > On Tuesday 10 July 2007 20:05, Scott Wood wrote:
> >>Why are you also moving mpc82xx_ads_show_cpuinfo() to the board file?
> >>It's not really ADS-specific; it should just be renamed.
> >
> > For the MPC82xx ADS boards, mpc82xx_ads_show_cpuinfo() prints
> >
> > Vendor : Freescale Semiconductor
> > Machine : PQ2 ADS PowerPC
> >
> > The vendor string is hardcoded to "Freescale Semiconductor", and the
> > machine string is defined in pq2ads.h. What should show_cpuinfo() print ?
> > Should the vendor be the board vendor or the CPU vendor ? What about the
> > machine ?
>
> Ah, I missed that. I'd just get rid of "Vendor" altogether, and include
> the vendor name in the machine name.
Is there any standard/documentation regarding what show_cpuinfo should print ?
Should it show CPU information only, or board information as well ? What
about the memory size, clock settings, ... ? What are the meanings
of "vendor" and "machine" ?
--
Laurent Pinchart
CSE Semaphore Belgium
^ permalink raw reply
* Re: [PATCH] [POWERPC] Move generic MPC82xx functions out of ADS-specific
From: Laurent Pinchart @ 2007-07-12 15:04 UTC (permalink / raw)
To: Scott Wood; +Cc: Vitaly Bordug, linuxppc-embedded
In-Reply-To: <4694F66D.2010907@freescale.com>
Hi Scott,
On Wednesday 11 July 2007 17:25, Scott Wood wrote:
> Laurent Pinchart wrote:
> > On Tuesday 10 July 2007 20:05, Scott Wood wrote:
> >>Why are you also moving mpc82xx_ads_show_cpuinfo() to the board file?
> >>It's not really ADS-specific; it should just be renamed.
> >
> > For the MPC82xx ADS boards, mpc82xx_ads_show_cpuinfo() prints
> >
> > Vendor : Freescale Semiconductor
> > Machine : PQ2 ADS PowerPC
> >
> > The vendor string is hardcoded to "Freescale Semiconductor", and the
> > machine string is defined in pq2ads.h. What should show_cpuinfo() print ?
> > Should the vendor be the board vendor or the CPU vendor ? What about the
> > machine ?
>
> Ah, I missed that. I'd just get rid of "Vendor" altogether, and include
> the vendor name in the machine name.
Is there any standard/documentation regarding what show_cpuinfo should print ?
Should it show CPU information only, or board information as well ? What
about the memory size, clock settings, ... ? What are the meanings
of "vendor" and "machine" ?
--
Laurent Pinchart
CSE Semaphore Belgium
^ permalink raw reply
* Re: [kernel-2.6.19]Marvell GT-64260 and Ethernet
From: Brian Waite @ 2007-07-12 14:50 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <4693861F.2000403@genesi-usa.com>
On Tuesday 10 July 2007, Matt Sealey wrote:
> Isn't the ethernet the same on the 64260, 64360, 64460?
>
> There's definitely a driver for 6436x and above..
There was some work done back in the early 2.6 timeframe to make a unified
360/260 driver. I worked on in a while ago (2+ years) I think the reason you
don't see it in the tree, is because we all stopped using the 260 and went to
the 360 as fast as possible.
gt64260_eth.c ill not jus work. A lot of work (Mark Greer etc) was done in
refactoring most of the Marvell support from 2.4->2.6. You might get away
with setting up the platfrom correctly for the 260. Check out the ppc/syslib
directory. You might find some clues there,
Thanks
Brian
^ permalink raw reply
* Re: [PATCH] [POWERPC] Move generic MPC82xx functions out of ADS-specific
From: Laurent Pinchart @ 2007-07-12 14:57 UTC (permalink / raw)
To: Scott Wood; +Cc: Vitaly Bordug, linuxppc-embedded
In-Reply-To: <4694F66D.2010907@freescale.com>
Hi Scott,
On Wednesday 11 July 2007 17:25, Scott Wood wrote:
> Laurent Pinchart wrote:
> > On Tuesday 10 July 2007 20:05, Scott Wood wrote:
> >>Why are you also moving mpc82xx_ads_show_cpuinfo() to the board file?
> >>It's not really ADS-specific; it should just be renamed.
> >
> > For the MPC82xx ADS boards, mpc82xx_ads_show_cpuinfo() prints
> >
> > Vendor : Freescale Semiconductor
> > Machine : PQ2 ADS PowerPC
> >
> > The vendor string is hardcoded to "Freescale Semiconductor", and the
> > machine string is defined in pq2ads.h. What should show_cpuinfo() print ?
> > Should the vendor be the board vendor or the CPU vendor ? What about the
> > machine ?
>
> Ah, I missed that. I'd just get rid of "Vendor" altogether, and include
> the vendor name in the machine name.
Is there any standard/documentation regarding what show_cpuinfo should print ?
Should it show CPU information only, or board information as well ? What
about the memory size, clock settings, ... ? What are the meanings
of "vendor" and "machine" ?
--
Laurent Pinchart
CSE Semaphore Belgium
^ permalink raw reply
* The kernel source in RAM is covered by data
From: Nicolas Mederle @ 2007-07-12 14:30 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-embedded
Hi,
I have port Linux on a PowerPc board. I have the following problems,
the kernel source is covered by data.
For example, after the kernel unzip by the loader, I have this mapping :
_start:
00000000: nop
00000004: nop
00000008: nop
__start:
0000000c: mr r31,r3
00000010: mr r30,r4
00000014: li r24,0
00000018: bl early_init
0000001c: bl mmu_off
__after_mmu_off:
00000020: bl clear_bats
00000024: bl flush_tlbs
00000028: bl initial_bats
0000002c: bl setup_disp_bat
00000030: bl reloc_offset
When the kernel launch the init process, I have an PageFault error. And
the mapping is the following :
_start:
00000000: .long 0
00000004: .long 0xB0
00000008: .long 0x67DC28
__start:
0000000c: .long 0x3C5FD0
00000010: .long 0x1031C
00000014: .long 0x8001032
00000018: .long 0
0000001c: .long 4
__after_mmu_off:
00000020: .long 1
00000024: .long 0x10590
00000028: .long 0x1032
0000002c: .long 0x1031C
00000030: .long 0x320000
Why the kernel space is modified? I have forgot a config in the kernel
config? the advanced setup kernel config is the following :
CONFIG_ADVANCED_OPTIONS=y
CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE_BOOL=y
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START_BOOL=y
CONFIG_KERNEL_START=0x0
# CONFIG_TASK_SIZE_BOOL is not set
CONFIG_TASK_SIZE=0x80000000
CONFIG_BOOT_LOAD_BOOL=y
CONFIG_BOOT_LOAD=0x00400000
Thanks for your feedback,
Nicolas MEDERLE.
--
Cordialement,
Nicolas MEDERLE.
^ permalink raw reply
* Re: Tickless Hz/hrtimers/etc. on PowerPC
From: Sergei Shtylyov @ 2007-07-12 14:11 UTC (permalink / raw)
To: Matt Sealey; +Cc: linuxppc-dev, Domen Puncer
In-Reply-To: <20070712065104.GI4375@moe.telargo.com>
[-- Attachment #1: Type: text/plain, Size: 2290 bytes --]
Hello.
Domen Puncer wrote:
>>Does anyone have the definitive patchset to enable the tickless hz,
>>some kind of hrtimer and the other related improvements in the
>>PowerPC tree?
> I use attached patches for tickless.
> Order in which they're applied:
> PowerPC_GENERIC_CLOCKEVENTS.patch
That's my patch which used to have both description and signoff that I'm
not seeing in the attached version...
> PowerPC_GENERIC_TIME.linux-2.6.18-rc6_timeofday-arch-ppc_C6.patch
This one should come first of all, I'd say...
Note that it breaks TOD vsyscalls, so you need my patch that removes
support for those for the time being (i.e. until Tony hopefully fixes this
:-). Also, there was a patch implementing read_persistent_clock() and getting
rid of the code setting xtime in time_init(). Attaching them both...
> PowerPC_enable_HRT_and_dynticks_support.patch
Again looks like my patch with description/signoff missing for whatever
reason...
> PowerPC_no_hz_fix.patch
This has nothing to do with CONFIG_NO_HZ per se -- it fixes the
compilation error introduced by John's patch.
> tickless-enable.patch
That one doesn't look quite right...
> HTH
> Domen
[...]
> ------------------------------------------------------------------------
>
> This is needed for hrtimer_switch_to_hres() to get called.
> hrtimer_run_queues()
> |-tick_check_oneshot_change()
> | \-timekeeping_is_continuous()
> | \- flags check
> \-hrtimer_switch_to_hres()
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
> Index: work-powerpc.git/arch/powerpc/kernel/time.c
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/kernel/time.c
> +++ work-powerpc.git/arch/powerpc/kernel/time.c
> @@ -1039,6 +1039,7 @@ struct clocksource clocksource_timebase
> .mask = (cycle_t)-1,
> .mult = 0,
> .shift = 22,
> + .flags = CLOCK_SOURCE_VALID_FOR_HRES,
> };
Hm, has the flag name changed from CLOCK_SOURCE_IS_CONTINOUS? I'm seeign
both there flags, therefore it must be CLOCK_SOURCE_IS_CONTINOUS, not
CLOCK_SOURCE_VALID_FOR_HRES.
WBR, Sergei
PS: All attached patches are against 2.6.21-rt2 -- fitting them into the
current (or whatever) version of the kernel is left as an excercise to the
readers. ;-)
[-- Attachment #2: ppc-remove-broken-vsyscalls.patch --]
[-- Type: text/x-patch, Size: 23295 bytes --]
Remove PowerPC vsyscalls that were broken by the generic TOD patch.
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
---
Since there's still no working PowerPC TOD vsyscalls fix, and they continue to
be broken in the RT patch, I've respun this patch again...
arch/powerpc/kernel/vdso32/gettimeofday.S | 322 ------------------------------
arch/powerpc/kernel/vdso64/gettimeofday.S | 254 -----------------------
arch/powerpc/kernel/asm-offsets.c | 15 -
arch/powerpc/kernel/smp.c | 2
arch/powerpc/kernel/vdso32/Makefile | 2
arch/powerpc/kernel/vdso32/datapage.S | 18 -
arch/powerpc/kernel/vdso32/vdso32.lds.S | 4
arch/powerpc/kernel/vdso64/Makefile | 2
arch/powerpc/kernel/vdso64/datapage.S | 18 -
arch/powerpc/kernel/vdso64/vdso64.lds.S | 4
include/asm-powerpc/time.h | 20 -
include/asm-powerpc/vdso_datapage.h | 14 -
12 files changed, 2 insertions(+), 673 deletions(-)
Index: linux-2.6/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6/arch/powerpc/kernel/asm-offsets.c
@@ -267,16 +267,7 @@ int main(void)
#endif /* ! CONFIG_PPC64 */
/* datapage offsets for use by vdso */
- DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct vdso_data, tb_orig_stamp));
- DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct vdso_data, tb_ticks_per_sec));
- DEFINE(CFG_TB_TO_XS, offsetof(struct vdso_data, tb_to_xs));
- DEFINE(CFG_STAMP_XSEC, offsetof(struct vdso_data, stamp_xsec));
- DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct vdso_data, tb_update_count));
- DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct vdso_data, tz_minuteswest));
- DEFINE(CFG_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
- DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
- DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
#ifdef CONFIG_PPC64
DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
@@ -297,12 +288,6 @@ int main(void)
DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
- /* Other bits used by the vdso */
- DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
- DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
- DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
- DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
-
#ifdef CONFIG_BUG
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
#endif
Index: linux-2.6/arch/powerpc/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6/arch/powerpc/kernel/smp.c
@@ -308,8 +308,6 @@ void smp_call_function_interrupt(void)
}
}
-extern struct gettimeofday_struct do_gtod;
-
struct thread_info *current_set[NR_CPUS];
DECLARE_PER_CPU(unsigned int, pvr);
Index: linux-2.6/arch/powerpc/kernel/vdso32/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso32/Makefile
+++ linux-2.6/arch/powerpc/kernel/vdso32/Makefile
@@ -1,7 +1,7 @@
# List of files in the vdso, has to be asm only for now
-obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
+obj-vdso32 = sigtramp.o datapage.o cacheflush.o note.o
# Build rules
Index: linux-2.6/arch/powerpc/kernel/vdso32/datapage.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso32/datapage.S
+++ linux-2.6/arch/powerpc/kernel/vdso32/datapage.S
@@ -65,21 +65,3 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_ma
blr
.cfi_endproc
V_FUNCTION_END(__kernel_get_syscall_map)
-
-/*
- * void unsigned long long __kernel_get_tbfreq(void);
- *
- * returns the timebase frequency in HZ
- */
-V_FUNCTION_BEGIN(__kernel_get_tbfreq)
- .cfi_startproc
- mflr r12
- .cfi_register lr,r12
- bl __get_datapage@local
- lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
- lwz r3,CFG_TB_TICKS_PER_SEC(r3)
- mtlr r12
- crclr cr0*4+so
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_get_tbfreq)
Index: linux-2.6/arch/powerpc/kernel/vdso32/gettimeofday.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Userland implementation of gettimeofday() for 32 bits processes in a
- * ppc64 kernel for use in the vDSO
- *
- * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org,
- * IBM Corp.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/vdso.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
- .text
-/*
- * Exact prototype of gettimeofday
- *
- * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
- *
- */
-V_FUNCTION_BEGIN(__kernel_gettimeofday)
- .cfi_startproc
- mflr r12
- .cfi_register lr,r12
-
- mr r10,r3 /* r10 saves tv */
- mr r11,r4 /* r11 saves tz */
- bl __get_datapage@local /* get data page */
- mr r9, r3 /* datapage ptr in r9 */
- bl __do_get_xsec@local /* get xsec from tb & kernel */
- bne- 2f /* out of line -> do syscall */
-
- /* seconds are xsec >> 20 */
- rlwinm r5,r4,12,20,31
- rlwimi r5,r3,12,0,19
- stw r5,TVAL32_TV_SEC(r10)
-
- /* get remaining xsec and convert to usec. we scale
- * up remaining xsec by 12 bits and get the top 32 bits
- * of the multiplication
- */
- rlwinm r5,r4,12,0,19
- lis r6,1000000@h
- ori r6,r6,1000000@l
- mulhwu r5,r5,r6
- stw r5,TVAL32_TV_USEC(r10)
-
- cmpli cr0,r11,0 /* check if tz is NULL */
- beq 1f
- lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
- lwz r5,CFG_TZ_DSTTIME(r9)
- stw r4,TZONE_TZ_MINWEST(r11)
- stw r5,TZONE_TZ_DSTTIME(r11)
-
-1: mtlr r12
- crclr cr0*4+so
- li r3,0
- blr
-
-2:
- mtlr r12
- mr r3,r10
- mr r4,r11
- li r0,__NR_gettimeofday
- sc
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_gettimeofday)
-
-/*
- * Exact prototype of clock_gettime()
- *
- * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
- *
- */
-V_FUNCTION_BEGIN(__kernel_clock_gettime)
- .cfi_startproc
- /* Check for supported clock IDs */
- cmpli cr0,r3,CLOCK_REALTIME
- cmpli cr1,r3,CLOCK_MONOTONIC
- cror cr0*4+eq,cr0*4+eq,cr1*4+eq
- bne cr0,99f
-
- mflr r12 /* r12 saves lr */
- .cfi_register lr,r12
- mr r10,r3 /* r10 saves id */
- mr r11,r4 /* r11 saves tp */
- bl __get_datapage@local /* get data page */
- mr r9,r3 /* datapage ptr in r9 */
- beq cr1,50f /* if monotonic -> jump there */
-
- /*
- * CLOCK_REALTIME
- */
-
- bl __do_get_xsec@local /* get xsec from tb & kernel */
- bne- 98f /* out of line -> do syscall */
-
- /* seconds are xsec >> 20 */
- rlwinm r5,r4,12,20,31
- rlwimi r5,r3,12,0,19
- stw r5,TSPC32_TV_SEC(r11)
-
- /* get remaining xsec and convert to nsec. we scale
- * up remaining xsec by 12 bits and get the top 32 bits
- * of the multiplication, then we multiply by 1000
- */
- rlwinm r5,r4,12,0,19
- lis r6,1000000@h
- ori r6,r6,1000000@l
- mulhwu r5,r5,r6
- mulli r5,r5,1000
- stw r5,TSPC32_TV_NSEC(r11)
- mtlr r12
- crclr cr0*4+so
- li r3,0
- blr
-
- /*
- * CLOCK_MONOTONIC
- */
-
-50: bl __do_get_xsec@local /* get xsec from tb & kernel */
- bne- 98f /* out of line -> do syscall */
-
- /* seconds are xsec >> 20 */
- rlwinm r6,r4,12,20,31
- rlwimi r6,r3,12,0,19
-
- /* get remaining xsec and convert to nsec. we scale
- * up remaining xsec by 12 bits and get the top 32 bits
- * of the multiplication, then we multiply by 1000
- */
- rlwinm r7,r4,12,0,19
- lis r5,1000000@h
- ori r5,r5,1000000@l
- mulhwu r7,r7,r5
- mulli r7,r7,1000
-
- /* now we must fixup using wall to monotonic. We need to snapshot
- * that value and do the counter trick again. Fortunately, we still
- * have the counter value in r8 that was returned by __do_get_xsec.
- * At this point, r6,r7 contain our sec/nsec values, r3,r4 and r5
- * can be used
- */
-
- lwz r3,WTOM_CLOCK_SEC(r9)
- lwz r4,WTOM_CLOCK_NSEC(r9)
-
- /* We now have our result in r3,r4. We create a fake dependency
- * on that result and re-check the counter
- */
- or r5,r4,r3
- xor r0,r5,r5
- add r9,r9,r0
-#ifdef CONFIG_PPC64
- lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
- lwz r0,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
- cmpl cr0,r8,r0 /* check if updated */
- bne- 50b
-
- /* Calculate and store result. Note that this mimmics the C code,
- * which may cause funny results if nsec goes negative... is that
- * possible at all ?
- */
- add r3,r3,r6
- add r4,r4,r7
- lis r5,NSEC_PER_SEC@h
- ori r5,r5,NSEC_PER_SEC@l
- cmpl cr0,r4,r5
- cmpli cr1,r4,0
- blt 1f
- subf r4,r5,r4
- addi r3,r3,1
-1: bge cr1,1f
- addi r3,r3,-1
- add r4,r4,r5
-1: stw r3,TSPC32_TV_SEC(r11)
- stw r4,TSPC32_TV_NSEC(r11)
-
- mtlr r12
- crclr cr0*4+so
- li r3,0
- blr
-
- /*
- * syscall fallback
- */
-98:
- mtlr r12
- mr r3,r10
- mr r4,r11
-99:
- li r0,__NR_clock_gettime
- sc
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_clock_gettime)
-
-
-/*
- * Exact prototype of clock_getres()
- *
- * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
- *
- */
-V_FUNCTION_BEGIN(__kernel_clock_getres)
- .cfi_startproc
- /* Check for supported clock IDs */
- cmpwi cr0,r3,CLOCK_REALTIME
- cmpwi cr1,r3,CLOCK_MONOTONIC
- cror cr0*4+eq,cr0*4+eq,cr1*4+eq
- bne cr0,99f
-
- li r3,0
- cmpli cr0,r4,0
- crclr cr0*4+so
- beqlr
- lis r5,CLOCK_REALTIME_RES@h
- ori r5,r5,CLOCK_REALTIME_RES@l
- stw r3,TSPC32_TV_SEC(r4)
- stw r5,TSPC32_TV_NSEC(r4)
- blr
-
- /*
- * syscall fallback
- */
-99:
- li r0,__NR_clock_getres
- sc
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_clock_getres)
-
-
-/*
- * This is the core of gettimeofday() & friends, it returns the xsec
- * value in r3 & r4 and expects the datapage ptr (non clobbered)
- * in r9. clobbers r0,r4,r5,r6,r7,r8.
- * When returning, r8 contains the counter value that can be reused
- * by the monotonic clock implementation
- */
-__do_get_xsec:
- .cfi_startproc
- /* Check for update count & load values. We use the low
- * order 32 bits of the update count
- */
-#ifdef CONFIG_PPC64
-1: lwz r8,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
-1: lwz r8,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
- andi. r0,r8,1 /* pending update ? loop */
- bne- 1b
- xor r0,r8,r8 /* create dependency */
- add r9,r9,r0
-
- /* Load orig stamp (offset to TB) */
- lwz r5,CFG_TB_ORIG_STAMP(r9)
- lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
-
- /* Get a stable TB value */
-2: mftbu r3
- mftbl r4
- mftbu r0
- cmpl cr0,r3,r0
- bne- 2b
-
- /* Substract tb orig stamp. If the high part is non-zero, we jump to
- * the slow path which call the syscall.
- * If it's ok, then we have our 32 bits tb_ticks value in r7
- */
- subfc r7,r6,r4
- subfe. r0,r5,r3
- bne- 3f
-
- /* Load scale factor & do multiplication */
- lwz r5,CFG_TB_TO_XS(r9) /* load values */
- lwz r6,(CFG_TB_TO_XS+4)(r9)
- mulhwu r4,r7,r5
- mulhwu r6,r7,r6
- mullw r0,r7,r5
- addc r6,r6,r0
-
- /* At this point, we have the scaled xsec value in r4 + XER:CA
- * we load & add the stamp since epoch
- */
- lwz r5,CFG_STAMP_XSEC(r9)
- lwz r6,(CFG_STAMP_XSEC+4)(r9)
- adde r4,r4,r6
- addze r3,r5
-
- /* We now have our result in r3,r4. We create a fake dependency
- * on that result and re-check the counter
- */
- or r6,r4,r3
- xor r0,r6,r6
- add r9,r9,r0
-#ifdef CONFIG_PPC64
- lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
- lwz r0,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
- cmpl cr0,r8,r0 /* check if updated */
- bne- 1b
-
- /* Warning ! The caller expects CR:EQ to be set to indicate a
- * successful calculation (so it won't fallback to the syscall
- * method). We have overriden that CR bit in the counter check,
- * but fortunately, the loop exit condition _is_ CR:EQ set, so
- * we can exit safely here. If you change this code, be careful
- * of that side effect.
- */
-3: blr
- .cfi_endproc
Index: linux-2.6/arch/powerpc/kernel/vdso32/vdso32.lds.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ linux-2.6/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -117,10 +117,6 @@ VERSION
global:
__kernel_datapage_offset; /* Has to be there for the kernel to find */
__kernel_get_syscall_map;
- __kernel_gettimeofday;
- __kernel_clock_gettime;
- __kernel_clock_getres;
- __kernel_get_tbfreq;
__kernel_sync_dicache;
__kernel_sync_dicache_p5;
__kernel_sigtramp32;
Index: linux-2.6/arch/powerpc/kernel/vdso64/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso64/Makefile
+++ linux-2.6/arch/powerpc/kernel/vdso64/Makefile
@@ -1,6 +1,6 @@
# List of files in the vdso, has to be asm only for now
-obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
+obj-vdso64 = sigtramp.o datapage.o cacheflush.o note.o
# Build rules
Index: linux-2.6/arch/powerpc/kernel/vdso64/datapage.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso64/datapage.S
+++ linux-2.6/arch/powerpc/kernel/vdso64/datapage.S
@@ -65,21 +65,3 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_ma
blr
.cfi_endproc
V_FUNCTION_END(__kernel_get_syscall_map)
-
-
-/*
- * void unsigned long __kernel_get_tbfreq(void);
- *
- * returns the timebase frequency in HZ
- */
-V_FUNCTION_BEGIN(__kernel_get_tbfreq)
- .cfi_startproc
- mflr r12
- .cfi_register lr,r12
- bl V_LOCAL_FUNC(__get_datapage)
- ld r3,CFG_TB_TICKS_PER_SEC(r3)
- mtlr r12
- crclr cr0*4+so
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_get_tbfreq)
Index: linux-2.6/arch/powerpc/kernel/vdso64/gettimeofday.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ /dev/null
@@ -1,254 +0,0 @@
-
- /*
- * Userland implementation of gettimeofday() for 64 bits processes in a
- * ppc64 kernel for use in the vDSO
- *
- * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
- * IBM Corp.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/vdso.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
- .text
-/*
- * Exact prototype of gettimeofday
- *
- * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
- *
- */
-V_FUNCTION_BEGIN(__kernel_gettimeofday)
- .cfi_startproc
- mflr r12
- .cfi_register lr,r12
-
- mr r11,r3 /* r11 holds tv */
- mr r10,r4 /* r10 holds tz */
- bl V_LOCAL_FUNC(__get_datapage) /* get data page */
- bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
- lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
- ori r7,r7,16960
- rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
- rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
- std r5,TVAL64_TV_SEC(r11) /* store sec in tv */
- subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
- mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
- * XSEC_PER_SEC
- */
- rldicl r0,r0,44,20
- cmpldi cr0,r10,0 /* check if tz is NULL */
- std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
- beq 1f
- lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
- lwz r5,CFG_TZ_DSTTIME(r3)
- stw r4,TZONE_TZ_MINWEST(r10)
- stw r5,TZONE_TZ_DSTTIME(r10)
-1: mtlr r12
- crclr cr0*4+so
- li r3,0 /* always success */
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_gettimeofday)
-
-
-/*
- * Exact prototype of clock_gettime()
- *
- * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
- *
- */
-V_FUNCTION_BEGIN(__kernel_clock_gettime)
- .cfi_startproc
- /* Check for supported clock IDs */
- cmpwi cr0,r3,CLOCK_REALTIME
- cmpwi cr1,r3,CLOCK_MONOTONIC
- cror cr0*4+eq,cr0*4+eq,cr1*4+eq
- bne cr0,99f
-
- mflr r12 /* r12 saves lr */
- .cfi_register lr,r12
- mr r10,r3 /* r10 saves id */
- mr r11,r4 /* r11 saves tp */
- bl V_LOCAL_FUNC(__get_datapage) /* get data page */
- beq cr1,50f /* if monotonic -> jump there */
-
- /*
- * CLOCK_REALTIME
- */
-
- bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
-
- lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
- ori r7,r7,16960
- rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
- rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
- std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
- subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
- mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
- * XSEC_PER_SEC
- */
- rldicl r0,r0,44,20
- mulli r0,r0,1000 /* nsec = usec * 1000 */
- std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
-
- mtlr r12
- crclr cr0*4+so
- li r3,0
- blr
-
- /*
- * CLOCK_MONOTONIC
- */
-
-50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
-
- lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
- ori r7,r7,16960
- rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
- rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
- subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
- mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
- * XSEC_PER_SEC
- */
- rldicl r6,r0,44,20
- mulli r6,r6,1000 /* nsec = usec * 1000 */
-
- /* now we must fixup using wall to monotonic. We need to snapshot
- * that value and do the counter trick again. Fortunately, we still
- * have the counter value in r8 that was returned by __do_get_xsec.
- * At this point, r5,r6 contain our sec/nsec values.
- * can be used
- */
-
- lwa r4,WTOM_CLOCK_SEC(r3)
- lwa r7,WTOM_CLOCK_NSEC(r3)
-
- /* We now have our result in r4,r7. We create a fake dependency
- * on that result and re-check the counter
- */
- or r9,r4,r7
- xor r0,r9,r9
- add r3,r3,r0
- ld r0,CFG_TB_UPDATE_COUNT(r3)
- cmpld cr0,r0,r8 /* check if updated */
- bne- 50b
-
- /* Calculate and store result. Note that this mimmics the C code,
- * which may cause funny results if nsec goes negative... is that
- * possible at all ?
- */
- add r4,r4,r5
- add r7,r7,r6
- lis r9,NSEC_PER_SEC@h
- ori r9,r9,NSEC_PER_SEC@l
- cmpl cr0,r7,r9
- cmpli cr1,r7,0
- blt 1f
- subf r7,r9,r7
- addi r4,r4,1
-1: bge cr1,1f
- addi r4,r4,-1
- add r7,r7,r9
-1: std r4,TSPC64_TV_SEC(r11)
- std r7,TSPC64_TV_NSEC(r11)
-
- mtlr r12
- crclr cr0*4+so
- li r3,0
- blr
-
- /*
- * syscall fallback
- */
-98:
- mtlr r12
- mr r3,r10
- mr r4,r11
-99:
- li r0,__NR_clock_gettime
- sc
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_clock_gettime)
-
-
-/*
- * Exact prototype of clock_getres()
- *
- * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
- *
- */
-V_FUNCTION_BEGIN(__kernel_clock_getres)
- .cfi_startproc
- /* Check for supported clock IDs */
- cmpwi cr0,r3,CLOCK_REALTIME
- cmpwi cr1,r3,CLOCK_MONOTONIC
- cror cr0*4+eq,cr0*4+eq,cr1*4+eq
- bne cr0,99f
-
- li r3,0
- cmpli cr0,r4,0
- crclr cr0*4+so
- beqlr
- lis r5,CLOCK_REALTIME_RES@h
- ori r5,r5,CLOCK_REALTIME_RES@l
- std r3,TSPC64_TV_SEC(r4)
- std r5,TSPC64_TV_NSEC(r4)
- blr
-
- /*
- * syscall fallback
- */
-99:
- li r0,__NR_clock_getres
- sc
- blr
- .cfi_endproc
-V_FUNCTION_END(__kernel_clock_getres)
-
-
-/*
- * This is the core of gettimeofday(), it returns the xsec
- * value in r4 and expects the datapage ptr (non clobbered)
- * in r3. clobbers r0,r4,r5,r6,r7,r8
- * When returning, r8 contains the counter value that can be reused
- */
-V_FUNCTION_BEGIN(__do_get_xsec)
- .cfi_startproc
- /* check for update count & load values */
-1: ld r8,CFG_TB_UPDATE_COUNT(r3)
- andi. r0,r8,1 /* pending update ? loop */
- bne- 1b
- xor r0,r8,r8 /* create dependency */
- add r3,r3,r0
-
- /* Get TB & offset it. We use the MFTB macro which will generate
- * workaround code for Cell.
- */
- MFTB(r7)
- ld r9,CFG_TB_ORIG_STAMP(r3)
- subf r7,r9,r7
-
- /* Scale result */
- ld r5,CFG_TB_TO_XS(r3)
- mulhdu r7,r7,r5
-
- /* Add stamp since epoch */
- ld r6,CFG_STAMP_XSEC(r3)
- add r4,r6,r7
-
- xor r0,r4,r4
- add r3,r3,r0
- ld r0,CFG_TB_UPDATE_COUNT(r3)
- cmpld cr0,r0,r8 /* check if updated */
- bne- 1b
- blr
- .cfi_endproc
-V_FUNCTION_END(__do_get_xsec)
Index: linux-2.6/arch/powerpc/kernel/vdso64/vdso64.lds.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ linux-2.6/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -115,10 +115,6 @@ VERSION
global:
__kernel_datapage_offset; /* Has to be there for the kernel to find */
__kernel_get_syscall_map;
- __kernel_gettimeofday;
- __kernel_clock_gettime;
- __kernel_clock_getres;
- __kernel_get_tbfreq;
__kernel_sync_dicache;
__kernel_sync_dicache_p5;
__kernel_sigtramp_rt64;
Index: linux-2.6/include/asm-powerpc/time.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/time.h
+++ linux-2.6/include/asm-powerpc/time.h
@@ -48,26 +48,6 @@ extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
#define DEFAULT_TB_FREQ 125000000UL
-/*
- * By putting all of this stuff into a single struct we
- * reduce the number of cache lines touched by do_gettimeofday.
- * Both by collecting all of the data in one cache line and
- * by touching only one TOC entry on ppc64.
- */
-struct gettimeofday_vars {
- u64 tb_to_xs;
- u64 stamp_xsec;
- u64 tb_orig_stamp;
-};
-
-struct gettimeofday_struct {
- unsigned long tb_ticks_per_sec;
- struct gettimeofday_vars vars[2];
- struct gettimeofday_vars * volatile varp;
- unsigned var_idx;
- unsigned tb_to_us;
-};
-
struct div_result {
u64 result_high;
u64 result_low;
Index: linux-2.6/include/asm-powerpc/vdso_datapage.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/vdso_datapage.h
+++ linux-2.6/include/asm-powerpc/vdso_datapage.h
@@ -74,11 +74,6 @@ struct vdso_data {
__u32 icache_size; /* L1 i-cache size 0x68 */
__u32 icache_line_size; /* L1 i-cache line size 0x6C */
- /* those additional ones don't have to be located anywhere
- * special as they were not part of the original systemcfg
- */
- __s32 wtom_clock_sec; /* Wall to monotonic clock */
- __s32 wtom_clock_nsec;
__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */
__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
};
@@ -89,15 +84,6 @@ struct vdso_data {
* And here is the simpler 32 bits version
*/
struct vdso_data {
- __u64 tb_orig_stamp; /* Timebase at boot 0x30 */
- __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
- __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
- __u64 stamp_xsec; /* 0x48 */
- __u32 tb_update_count; /* Timebase atomicity ctr 0x50 */
- __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
- __u32 tz_dsttime; /* Type of dst correction 0x5C */
- __s32 wtom_clock_sec; /* Wall to monotonic clock */
- __s32 wtom_clock_nsec;
__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
};
[-- Attachment #3: gtod-persistent-clock-support-ppc.patch --]
[-- Type: text/x-patch, Size: 2969 bytes --]
Here's the read_persistent_clock() implementation for PowerPC.
I'm deliberately renaming get_boot_time() despite it's not static as it
doesn't get called from anywhere else.
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
---
Have almost forgotten about this one... :-)
This patch hasn't received a good testing though -- at least it doesn't break
without RTC... ;-)
arch/powerpc/kernel/time.c | 62 ++++++++++++++++++++-------------------------
1 files changed, 28 insertions(+), 34 deletions(-)
Index: linux-2.6/arch/powerpc/kernel/time.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/time.c
+++ linux-2.6/arch/powerpc/kernel/time.c
@@ -762,31 +762,46 @@ void __init generic_calibrate_decr(void)
#endif
}
-unsigned long get_boot_time(void)
+unsigned long read_persistent_clock(void)
{
- struct rtc_time tm;
+ unsigned long time = 0;
+ static int first = 1;
+
+ if (first && ppc_md.time_init) {
+ timezone_offset = ppc_md.time_init();
+
+ /* If platform provided a timezone (pmac), we correct the time */
+ if (timezone_offset) {
+ sys_tz.tz_minuteswest = -timezone_offset / 60;
+ sys_tz.tz_dsttime = 0;
+ }
+ }
if (ppc_md.get_boot_time)
- return ppc_md.get_boot_time();
- if (!ppc_md.get_rtc_time)
- return 0;
- ppc_md.get_rtc_time(&tm);
- return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
+ time = ppc_md.get_boot_time();
+ else if (ppc_md.get_rtc_time) {
+ struct rtc_time tm;
+
+ ppc_md.get_rtc_time(&tm);
+ time = mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+ time -= timezone_offset;
+
+ if (first) {
+ last_rtc_update = time;
+ first = 0;
+ }
+ return time;
}
/* This function is only called on the boot processor */
void __init time_init(void)
{
- unsigned long flags;
- unsigned long tm = 0;
struct div_result res;
u64 scale, x;
unsigned shift;
- if (ppc_md.time_init != NULL)
- timezone_offset = ppc_md.time_init();
-
if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
ppc_tb_freq = 1000000000;
@@ -860,27 +875,6 @@ void __init time_init(void)
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
- tm = get_boot_time();
-
- write_seqlock_irqsave(&xtime_lock, flags);
-
- /* If platform provided a timezone (pmac), we correct the time */
- if (timezone_offset) {
- sys_tz.tz_minuteswest = -timezone_offset / 60;
- sys_tz.tz_dsttime = 0;
- tm -= timezone_offset;
- }
-
- xtime.tv_sec = tm;
- xtime.tv_nsec = 0;
-
- time_freq = 0;
-
- last_rtc_update = xtime.tv_sec;
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
#ifdef CONFIG_GENERIC_CLOCKEVENTS
decrementer_clockevent.mult = div_sc(ppc_tb_freq, NSEC_PER_SEC,
decrementer_clockevent.shift);
^ permalink raw reply
* Re: [Cbe-oss-dev] PS3 improved video mode autodetection for HDMI/DVI
From: Håvard Espeland @ 2007-07-12 14:06 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Linux/PPC Development, Cell Broadband Engine OSS Development,
Ben Collins
In-Reply-To: <Pine.LNX.4.62.0707121029320.12797@pademelon.sonytel.be>
On Thu, Jul 12, 2007 at 10:40:47AM +0200, Geert Uytterhoeven wrote:
> Hi,
>
> As of 8d28c70b27cb70cf01d21aab8e51a6dc43c10d70, Geoff's git tree[*] has
> improved support for video mode autodetection on both HDMI and DVI-D(+HDCP)
> monitors. By default the kernel will select the `best' videomode for your
> monitor, now also including VESA modes (e.g. 1920x1200). You can still override
> it with the traditional `video=' kernel command line option.
>
> If you're using a PS3 with a HDMI or DVI-D(+HDCP) monitor, please give it a
> try.
>
> If it fails, please add `#define DEBUG' to drivers/ps3/ps3av.c, send me the
> `Monitor Info' output in the kernel log (dmesg), and tell me which of the
> PS3 video modes (1-13) work and which don't. ps3av has a quirk database for
> monitors that advertise non-working modes, so it can probably be fixed.
> (BTW, even if autodetect works fine, I always welcome this information)
>
> In case you have a big pile of monitors at your site, you don't have to reboot
> to try them all. Just plug in the new monitor and run `ps3videomode -v 0' to
> switch to the best resolution of the newly-connected monitor.
Hi, the autodetect code does not work correctly with a LG L226WTQ
(native resolution 1680x1050). The detected mode (11) works fine without
fullscreen, but goes out of range with '-f'.
Resolutions w/o fullscreen:
OK: 2, 3, 7, 8, 11, 12
BAD: 1, 4, 5, 6, 9, 10, 13
Resolutions with fullscreen:
OK: 2, 3, 7, 8
BAD: 1, 4, 5, 6, 9, 10, 11, 12, 13
--
Håvard Espeland
Monitor Info: size 96
avport: 00
monitor_id: 1e 6d 4e 56 d7 2a 03 00 03 11
monitor_type: 02
monitor_name: L226WTQ
resolution_60: bits: 0000400d native: 00000000
resolution_50: bits: 00000000 native: 00000000
resolution_other: bits: 00000000 native: 00000000
resolution_vesa: bits: 00000001 native: 00000000
color space rgb: 01
color space yuv444: 00
color space yuv422: 00
color info red: X 028a Y 015e
color info green: X 012b Y 0272
color info blue: X 0097 Y 0048
color info white: X 0141 Y 0151
color info gamma: 000000dc
supported_AI: 00
speaker_info: 00
num of audio: 00
ps3av_hdmi_get_vid: Using supported resolution 11
ps3_av vuart_01: <- ps3av_probe:1016
<- ps3_system_bus_probe:376: vuart_01
ps3_system_bus_match:354: dev=5(vuart_02), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=10(ioc0_01), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=3(sb_04), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=1(sb_05), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=2(sb_06), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=1(sb_07), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=2(sb_08), drv=4(ps3_av): miss
ps3_system_bus_match:354: dev=9(ioc0_02), drv=4(ps3_av): mis
^ permalink raw reply
* Re: [PATCH 1/2] Kernel: Move all technical descriptons of the Device Tree Complier
From: Jon Loeliger @ 2007-07-12 13:08 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <18069.41758.420516.135000@cargo.ozlabs.ibm.com>
So, like, the other day Paul Mackerras mumbled:
> Jon Loeliger writes:
>
> > and its formats, command lines, descriptions, etc,
> > over to the Device Tree Compiler repositories now.
>
> Hrm, section II (DT block format) is a description of a kernel
> interface, and I think it should stay. After all, there's nothing
Hmm. That's a good point; I'll buy it. All of section II, then?
> I have no problem with that section being copied over to the dtc
> source.
>
> I also don't mind section IV being removed, although a sentence saying
> that dtc is useful for generating dtbs, and where to find dtc, would
> be useful.
I will respin the patch as suggested!
jdl
^ permalink raw reply
* Re: [PATCH 0/2] Move DTC Technical specs out of b-w-o.txt into DTC Repo
From: Jon Loeliger @ 2007-07-12 13:03 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <BFA74155-D32C-41F5-B61C-D9CE89A29B9B@kernel.crashing.org>
So, like, the other day Kumar Gala mumbled:
>
> On Jul 11, 2007, at 4:45 PM, Jon Loeliger wrote:
>
> > Folks,
> >
> > Here are two patches, one to the kernel, the other to
> > the DTC repo, that moves the technical description
> > portions of the booting-without-of.txt documentation
> > out of the kernel and into the DTC repository.
>
> Why remove it from the kernel? It seems like this part should change
> infrequently and it would be good to keep its documentation with the
> kernel as well?
Well, all the usual reasons. It will be improving over time,
and it makes much more sense to keep the documntation about
a system within the repository for that system. And rather
than have two copies, one of which will get out of sync,
I feel it makes more sense to relocate the DTC technical
descriptions to the DTC repository where it belongs.
And speaking of which, I will also be removing the already extant
and already way out of data copy of the booting-without-of.txt
from the DTC repo as well.
If a small summary of say, DTC command line usage is left in
b-w-o.txt as a Quick Ref, I'm fine with that, of course.
Thanks,
jdl
^ permalink raw reply
* Re: [RFC][PATCH 3/8] 4xx MMU
From: Josh Boyer @ 2007-07-12 12:40 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <2FE5C7E5-DF96-49C1-939E-39521A248F9B@kernel.crashing.org>
On Thu, 2007-07-12 at 02:09 -0500, Kumar Gala wrote:
> > Is it actually feasible to get to a point where
> > you can build a kernel that boots on both
> > 40x and 44x, or is it just too different?
>
> I'm guessing its too different since 40x probably has a real mode and
> 44x doesnt.
Among other things.
> However, I agree we should go ahead and rename 4xx to 40x at this
> point in arch/powerpc.
Yeah. See my response to Arnd about getting a git tree in place to do
it. RSN :)
josh
^ permalink raw reply
* RE: How to access physical memory from user space for MPC8260 chip
From: Fillod Stephane @ 2007-07-12 12:07 UTC (permalink / raw)
To: suresh suresh, linuxppc-embedded
suresh suresh wrote:
>I have to map physical memory to user space or kernel space. I am
writing >driver for MPC8260 chip and I want to know how to map any
32-bit address >space to user space and kernel space.
Your question is a linuxppc-embedded FAQ. User-land access is documented
in Denx's FAQ[1], and accessible through shorter URL[2]. For more=20
information, please follow this thread[3] (not ppc specific actually).
[1]
http://www.denx.de/twiki/bin/view/PPCEmbedded/DeviceDrivers#Section_Acce
ssingPeripheralsFromUserSpace
[2] http://tinyurl.com/6c7th
[3] http://article.gmane.org/gmane.linux.ports.ppc.embedded/5053
In kernel land, ioremap() is all you need.
Don't forget to use the 'eieio' asm instruction if you want explicit=20
I/O ordering.
Best Regards,
--=20
Stephane, the userland ioremap bot
^ permalink raw reply
* Re: [RFC 1/3] lro: Generic LRO for TCP traffic
From: Jan-Bernd Themann @ 2007-07-12 11:54 UTC (permalink / raw)
To: Evgeniy Polyakov
Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel, linux-ppc,
Christoph Raisch, Marcus Eder, Stefan Roscher
In-Reply-To: <20070712080137.GA25699@2ka.mipt.ru>
Hi Evgeniy
On Thursday 12 July 2007 10:01, Evgeniy Polyakov wrote:
> > +
> > + if (tcph->cwr || tcph->ece || tcph->urg || !tcph->ack || tcph->psh
> > + || tcph->rst || tcph->syn || tcph->fin)
> > + return -1;
>
> I think you do not want to break lro frame because of push flag - it is
> pretty common flag, which does not brak processing (and I'm not sure if
> it has any special meaning this days).
>
> > + if (INET_ECN_is_ce(ipv4_get_dsfield(iph)))
> > + return -1;
> > +
> > + if (tcph->doff != TCPH_LEN_WO_OPTIONS
> > + && tcph->doff != TCPH_LEN_W_TIMESTAMP)
> > + return -1;
> > +
> > + /* check tcp options (only timestamp allowed) */
> > + if (tcph->doff == TCPH_LEN_W_TIMESTAMP) {
> > + u32 *topt = (u32 *)(tcph + 1);
> > +
> > + if (*topt != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
> > + | (TCPOPT_TIMESTAMP << 8)
> > + | TCPOLEN_TIMESTAMP))
> > + return -1;
> > +
> > + /* timestamp should be in right order */
> > + topt++;
> > + if (lro_desc && (ntohl(lro_desc->tcp_rcv_tsval) > ntohl(*topt)))
> > + return -1;
>
> This still does not handle wrapping over 32 bits.
> What about
> if (lro_desc && after(ntohl(lro_desc->tcp_rcv_tsval), ntohl(*topt)))
> return -1;
Looks good, will change that
>
> > + /* timestamp reply should not be zero */
> > + topt++;
> > + if (*topt == 0)
> > + return -1;
> > + }
> > +
> > + return 0;
> > +}
>
> > +static struct net_lro_desc *lro_get_desc(struct net_lro_mgr *mgr,
> > + struct net_lro_desc *lro_arr,
> > + struct iphdr *iph,
> > + struct tcphdr *tcph)
> > +{
> > + struct net_lro_desc *lro_desc = NULL;
> > + struct net_lro_desc *tmp;
> > + int max_desc = mgr->max_desc;
> > + int i;
> > +
> > + for (i = 0; i < max_desc; i++) {
> > + tmp = &lro_arr[i];
> > + if (tmp->active)
> > + if (!lro_check_tcp_conn(tmp, iph, tcph)) {
> > + lro_desc = tmp;
> > + goto out;
> > + }
> > + }
>
> Ugh... What about tree structure or hash here?
Our initial version was based on the following assumptions (remember, 8 elements...):
- given a quota of 64 packets, it makes no sense to use huge arrays for LRO descriptors
(in our case 8 elements seem to work fine).
- trying to benefit from caching effects+branch prediction,
+ use the built in cacheline prefetch
I guess the array mechanism can be improved (finding free entries), but for the
initial version to see how the rest of the stack behaves with LRO
it might be ok this way.
Do you think a tree or hash would improve this with existing
caching designs (for a small number of elements)?
>
> > + for (i = 0; i < max_desc; i++) {
> > + if(!lro_arr[i].active) {
> > + lro_desc = &lro_arr[i];
> > + goto out;
> > + }
> > + }
> > +
> > +out:
> > + return lro_desc;
> > +}
>
> > +int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
> > + struct vlan_group *vgrp, u16 vlan_tag, void *priv)
> > +{
> > + struct net_lro_desc *lro_desc;
> > + struct iphdr *iph;
> > + struct tcphdr *tcph;
> > +
> > + if (!lro_mgr->get_ip_tcp_hdr
> > + || lro_mgr->get_ip_tcp_hdr(skb, &iph, &tcph, priv))
> > + goto out;
> > +
> > + lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
> > + if (!lro_desc)
> > + goto out;
>
> There is no protection of the descriptor array from accessing from
> different CPUs. Is it forbidden to share net_lro_mgr structure?
>
Currently we assume that netpoll runs with one device only on one cpu
at a time, and if there are multiple receive queues that can be processed
in parallel the traffic is usually sorted per receive queue. It would make
sense to use an own LRO "Manager" for each queue (would speed up the lookup)
Regards,
Jan-Bernd
^ permalink raw reply
* Re: [Cbe-oss-dev] PS3 improved video mode autodetection for HDMI/DVI
From: Sebastian Siewior @ 2007-07-12 12:10 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Linux/PPC Development, Cell Broadband Engine OSS Development,
Ben Collins
In-Reply-To: <Pine.LNX.4.62.0707121029320.12797@pademelon.sonytel.be>
* Geert Uytterhoeven | 2007-07-12 10:40:47 [+0200]:
>If you're using a PS3 with a HDMI or DVI-D(+HDCP) monitor, please give it a
>try.
Got 1920x1200 @60Hz on my Eizo FlexScan S2411W on boot. No quirk
required for that one :)
>(BTW, even if autodetect works fine, I always welcome this information)
Here it is:
Monitor Info: size 96
avport: 00
monitor_id: 15 c3 50 18 01 01 01 01 04 11
monitor_type: 02
monitor_name: S2411W
resolution_60: bits: 0000400d native: 00000000
resolution_50: bits: 00000000 native: 00000000
resolution_other: bits: 00000000 native: 00000000
resolution_vesa: bits: 00000009 native: 00000000
color space rgb: 01
color space yuv444: 00
color space yuv422: 00
color info red: X 028f Y 0152
color info green: X 0133 Y 026f
color info blue: X 009a Y 003d
color info white: X 0141 Y 0151
color info gamma: 000000dc
supported_AI: 00
speaker_info: 00
num of audio: 00
ps3av_hdmi_get_vid: Using supported resolution 15
ps3_av vuart_01: <- ps3av_probe:1014
>Geert Uytterhoeven
Sebastian
^ permalink raw reply
* Re: Tickless Hz/hrtimers/etc. on PowerPC
From: Matt Sealey @ 2007-07-12 12:07 UTC (permalink / raw)
To: Domen Puncer; +Cc: ppc-dev
In-Reply-To: <20070712065104.GI4375@moe.telargo.com>
Domen,
You wouldn't have tried these on the Efika yet, would you?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
Domen Puncer wrote:
> On 11/07/07 19:06 +0100, Matt Sealey wrote:
>> Does anyone have the definitive patchset to enable the tickless hz,
>> some kind of hrtimer and the other related improvements in the
>> PowerPC tree?
>
> I use attached patches for tickless.
> Order in which they're applied:
>
> PowerPC_GENERIC_CLOCKEVENTS.patch
> PowerPC_GENERIC_TIME.linux-2.6.18-rc6_timeofday-arch-ppc_C6.patch
> PowerPC_enable_HRT_and_dynticks_support.patch
> PowerPC_no_hz_fix.patch
> tickless-enable.patch
>
> HTH
>
>
> Domen
^ permalink raw reply
* Re: Tickless Hz/hrtimers/etc. on PowerPC
From: Matt Sealey @ 2007-07-12 12:07 UTC (permalink / raw)
To: Tony Breeds; +Cc: ppc-dev, Michael Neuling
In-Reply-To: <20070712064115.GO10345@bakeyournoodle.com>
Hi Tony,
What does "isn't quite right yet" mean? Broken, acts funny, or just
a messy patch?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
Tony Breeds wrote:
> On Wed, Jul 11, 2007 at 11:15:16PM +0100, Matt Sealey wrote:
>
>> And I don't want to run -rt or wireless-dev for the benefit of a single
>> feature. What I am after is something like Ingo Molnar throws out..
>> single patches done the old way, not git trees. It's so much easier to
>> handle and integrate for example into a Gentoo ebuild or to make a
>> tarball of accumulated patches from a certain release kernel.
>
> Hi Matt,
> In the near future I will have something that I can pass around
> for review. Which will be a quilt series of about 5 patches (based on
> mainline). I'll make sure to include you in the reviewers list. At
> this stage I'd hope they'll be in 2.6.24.
>
> I have HRT in a state where you can enable it and it works, but NO_HZ
> isn't quite right yet.
>
> Yours Tony
>
> linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
> Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
>
^ permalink raw reply
* Re: [patch 3/6] Add 8548 CDS PCI express controller node and PCI-X device node
From: Zang Roy-r61911 @ 2007-07-12 11:36 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <2EA16557-7960-4A1A-9D07-BDA3D8843460@kernel.crashing.org>
On Thu, 2007-07-12 at 17:00, Kumar Gala wrote:
> On Jul 12, 2007, at 3:27 AM, Zang Roy-r61911 wrote:
>
> > From: Roy Zang <tie-fei.zang@freescale.com>
> >
> > Add 8548 CDS PCI express controller node and PCI-X device node.
> > The current dts file is suitable for 8548 Rev 2.0 board with
> > Arcadia 3.1.
> > This kind of board combination is the most popular.
> >
> > Indentify pci, pcie host by compatible property "fsl,mpc85xx-pci"
> > and "fsl, mpc85xx-pciex".
> >
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > ---
> > Fix the PCI Express b,c,d, irq sense.
>
> is this the only fix, I've already applied a version of this to my
> tree (with the irq sense fix) and just want to make sure there isn't
> anything else.
I do not get more.
I'd like to enroll Segher's suggestion together with VIA chip function
in next step.
We need to make basic pcie work on 8548 CDS board first.
Thanks.
Roy
^ permalink raw reply
* How to access physical memory from user space for MPC8260 chip
From: suresh suresh @ 2007-07-12 10:07 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 234 bytes --]
Hi,
I have to map physical memory to user space or kernel space. I am writing
driver for MPC8260 chip and I want to know how to map any 32-bit address
space to user space and kernel space.
Please give me some ideas.
Thanks,
Suresh
[-- Attachment #2: Type: text/html, Size: 266 bytes --]
^ permalink raw reply
* RE: [PATCH 4/4] Add DMA engine driver for Freescale MPC8xxx processors.
From: Zhang Wei-r63237 @ 2007-07-12 10:06 UTC (permalink / raw)
To: Wood Scott-B07421; +Cc: linuxppc-dev, paulus
In-Reply-To: <20070711163438.GA17293@ld0162-tx32.am.freescale.net>
=20
> -----Original Message-----
> From: Wood Scott-B07421=20
>=20
> On Tue, Jul 10, 2007 at 05:45:26PM +0800, Zhang Wei wrote:
> > +config FSL_DMA
> > + bool "Freescale MPC8xxx DMA support"
> > + depends on DMA_ENGINE && (PPC_86xx || PPC_85xx)
>=20
> Remove the dependency on specific PPC chips... let the=20
> device tree say
> whether the hardware is present.
.... Remove it.
>=20
> > +static inline int fsl_dma_idle(struct fsl_dma_chan *fsl_chan)
> > +{
> > + return (((in_be32(&fsl_chan->reg_base->sr) &=20
> FSL_DMA_SR_CB) =3D=3D 0) &&
> > + ((in_be32(&fsl_chan->reg_base->mr) &=20
> FSL_DMA_MR_CC) =3D=3D 0));
> > +}
>=20
> I'm still not convinced that there's any reason to check=20
> MR_CC, even if
> the driver *did* set it.
>=20
Remove it.
> > + /* We need the descriptor to be aligned to 32bytes
> > + * for meeting FSL DMA specification requirement.
> > + */
> > + fsl_chan->desc_pool =3D=20
> dma_pool_create("fsl_dma_engine_desc_pool",
> > + fsl_chan->device->dev, sizeof(struct=20
> fsl_desc_sw),
> > + 32, 0);
> > + if (unlikely(!fsl_chan->desc_pool)) {
> > + dev_err(fsl_chan->device->dev, "No memory for=20
> channel %d "
> > + "descriptor dma pool.\n", fsl_chan->id);
> > + return 0;
> > + }
> > +
> > + /* Allocate list ring, and form the static list ring */
> > + for (i =3D 0; i < FSLDMA_LD_INIT_RING_SIZE; i++) {
> > + desc =3D fsl_dma_alloc_descriptor(fsl_chan->desc_pool,
> > + GFP_KERNEL);
>=20
> It'd be much simpler to allocate the entire ring at once. No need for
> linked lists, DMA pools, etc. Just a single dma_alloc_coherent.
>=20
I use a flexible ld ring size here. If there is no more free ring, the
driver can add new ld to the ring.
> In general, this driver seems far more complex than it needs to be.
>=20
> > + switch (fsl_chan->mode) {
> > + case FSL_DMA_EXTENDED:
>=20
> What benefit do we get out of using extended mode? If the=20
> driver can do
> everything it needs to with basic, with no performance=20
> penalty, why not
> always use basic?
>=20
Why there are extended mode in silicon? :) Since there are here, we use
it.
> > +static dma_cookie_t do_fsl_dma_memcpy(struct fsl_dma_chan=20
> *fsl_chan,
> > + dma_addr_t dest,
> > + dma_addr_t src, size_t len,
> > + dma_xfer_callback cb, void *data)
> > +{
> > + struct fsl_desc_sw *first =3D NULL, *prev =3D NULL, *list, *new;
> > + size_t copy;
> > + dma_cookie_t cookie;
> > + unsigned long flags;
> > + struct fsl_dma_device *fdev =3D fsl_chan->device;
> > + int err =3D 0;
> > + LIST_HEAD(link_chain);
> > +
> > + if (unlikely(!fsl_chan || !dest || !src))
> > + return -EFAULT;
>=20
> -EINVAL for fsl_chan, if you bother checking at all (I wouldn't; it
> doesn't come from untrusted code. Better to show a=20
> nasty-looking oops to
> bring attention to the problem).
>=20
> Don't check dest and src against NULL; zero is a potentially valid DMA
> address.
Ok. Do not check dest and src with NULL value. Hope the caller know what
he do.:)
>=20
> > + /* Stop the DMA */
> > + fsl_dma_halt(fsl_chan);
> > + /* Insert the ld descriptor to the LD ring */
> > + list_add(&ld->node, fsl_chan->enque);
> > + switch (fsl_chan->mode) {
> > + case FSL_DMA_EXTENDED:
> > + INSERT_LD_RING(fsl_chan, ld, list,=20
> next_ls_addr);
> > + break;
> > + case FSL_DMA_BASIC:
> > + INSERT_LD_RING(fsl_chan, ld, link,=20
> next_ln_addr);
> > + break;
> > + }
> > + spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
>=20
> It'd be nice if we didn't have to stop the DMA in order to insert new
> descriptors.
Since there is only happen at no more free ld in the ring. We need to
break the ld-ring and add new ld to it. So the most safe operation is to
stop DMA controller.
>=20
> > + /* cookie incr and addition to used_list must be atomic */
> > + cookie =3D fsl_chan->common.cookie;
> > + cookie++;
> > + if (cookie < 0)
> > + cookie =3D 1;
>=20
> Why not just use the index into the ring as the cookie?
The cookie will record all transfer by increased number. The ring index
is less for all transfer.
>=20
> > + stat =3D in_be32(&fsl_chan->reg_base->sr);
> > + dev_dbg(fsl_chan->device->dev, "event: channel %d, stat=20
> =3D 0x%x\n",
> > + fsl_chan->id, stat);
> > + if (!stat)
> > + return IRQ_NONE;
> > + busy =3D stat & (FSL_DMA_SR_CB);
> > + stat &=3D ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
>=20
> This masking must happen *before* the IRQ_NONE check.
>=20
Really? FSL_DMA_SR_CH is also a stat of event. And I need the
FSL_DMA_SR_CB status.
Thanks!
Wei.
^ permalink raw reply
* Re: [RFC 1/3] lro: Generic LRO for TCP traffic
From: Evgeniy Polyakov @ 2007-07-12 8:01 UTC (permalink / raw)
To: Jan-Bernd Themann
Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel, linux-ppc,
Christoph Raisch, Marcus Eder, Stefan Roscher
In-Reply-To: <200707111621.34376.ossthema@de.ibm.com>
Hi, Jan-Bernd.
I have couple of comments over implementation besides one you saw
previous time.
On Wed, Jul 11, 2007 at 04:21:34PM +0200, Jan-Bernd Themann (ossthema@de.ibm.com) wrote:
> +static int lro_tcp_ip_check(struct sk_buff *skb, struct iphdr *iph,
> + struct tcphdr *tcph, struct net_lro_desc *lro_desc)
> +{
> + /* check ip header: packet length */
> + if (ntohs(iph->tot_len) > skb->len)
> + return -1;
> +
> + if (TCP_PAYLOAD_LENGTH(iph, tcph) == 0)
> + return -1;
> +
> + if (iph->ihl != IPH_LEN_WO_OPTIONS)
> + return -1;
> +
> + if (tcph->cwr || tcph->ece || tcph->urg || !tcph->ack || tcph->psh
> + || tcph->rst || tcph->syn || tcph->fin)
> + return -1;
I think you do not want to break lro frame because of push flag - it is
pretty common flag, which does not brak processing (and I'm not sure if
it has any special meaning this days).
> + if (INET_ECN_is_ce(ipv4_get_dsfield(iph)))
> + return -1;
> +
> + if (tcph->doff != TCPH_LEN_WO_OPTIONS
> + && tcph->doff != TCPH_LEN_W_TIMESTAMP)
> + return -1;
> +
> + /* check tcp options (only timestamp allowed) */
> + if (tcph->doff == TCPH_LEN_W_TIMESTAMP) {
> + u32 *topt = (u32 *)(tcph + 1);
> +
> + if (*topt != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
> + | (TCPOPT_TIMESTAMP << 8)
> + | TCPOLEN_TIMESTAMP))
> + return -1;
> +
> + /* timestamp should be in right order */
> + topt++;
> + if (lro_desc && (ntohl(lro_desc->tcp_rcv_tsval) > ntohl(*topt)))
> + return -1;
This still does not handle wrapping over 32 bits.
What about
if (lro_desc && after(ntohl(lro_desc->tcp_rcv_tsval), ntohl(*topt)))
return -1;
> + /* timestamp reply should not be zero */
> + topt++;
> + if (*topt == 0)
> + return -1;
> + }
> +
> + return 0;
> +}
> +static struct net_lro_desc *lro_get_desc(struct net_lro_mgr *mgr,
> + struct net_lro_desc *lro_arr,
> + struct iphdr *iph,
> + struct tcphdr *tcph)
> +{
> + struct net_lro_desc *lro_desc = NULL;
> + struct net_lro_desc *tmp;
> + int max_desc = mgr->max_desc;
> + int i;
> +
> + for (i = 0; i < max_desc; i++) {
> + tmp = &lro_arr[i];
> + if (tmp->active)
> + if (!lro_check_tcp_conn(tmp, iph, tcph)) {
> + lro_desc = tmp;
> + goto out;
> + }
> + }
Ugh... What about tree structure or hash here?
> + for (i = 0; i < max_desc; i++) {
> + if(!lro_arr[i].active) {
> + lro_desc = &lro_arr[i];
> + goto out;
> + }
> + }
> +
> +out:
> + return lro_desc;
> +}
> +int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
> + struct vlan_group *vgrp, u16 vlan_tag, void *priv)
> +{
> + struct net_lro_desc *lro_desc;
> + struct iphdr *iph;
> + struct tcphdr *tcph;
> +
> + if (!lro_mgr->get_ip_tcp_hdr
> + || lro_mgr->get_ip_tcp_hdr(skb, &iph, &tcph, priv))
> + goto out;
> +
> + lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
> + if (!lro_desc)
> + goto out;
There is no protection of the descriptor array from accessing from
different CPUs. Is it forbidden to share net_lro_mgr structure?
--
Evgeniy Polyakov
^ 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