LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 06/13] IB/ehca: Set SEND_GRH flag for all non-LL UD QPs on eHCA2
From: Joachim Fenkes @ 2007-07-09 13:27 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

From: Stefan Roscher <stefan.roscher@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_qp.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index ffd1ce9..cbb8b5b 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1054,6 +1054,17 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 		 "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
 		 my_qp, ibqp->qp_num, statetrans);
 
+	/* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
+	 * in non-LL UD QPs.
+	 */
+	if ((my_qp->qp_type == IB_QPT_UD) &&
+	    (my_qp->ext_type != EQPT_LLQP) &&
+	    (statetrans == IB_QPST_INIT2RTR) &&
+	    (shca->hw_level >= 0x22)){
+		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+		mqpcb->send_grh_flag = 1;
+	}
+
 	/* sqe -> rts: set purge bit of bad wqe before actual trans */
 	if ((my_qp->qp_type == IB_QPT_UD ||
 	     my_qp->qp_type == IB_QPT_GSI ||
-- 
1.5.2

^ permalink raw reply related

* [PATCH 07/13] IB/ehca: Report RDMA atomic attributes in query_qp()
From: Joachim Fenkes @ 2007-07-09 13:28 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_qp.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index cbb8b5b..989f75e 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1491,6 +1491,9 @@ int ehca_query_qp(struct ib_qp *qp,
 	qp_attr->alt_port_num = qpcb->alt_phys_port;
 	qp_attr->alt_timeout = qpcb->timeout_al;
 
+	qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
+	qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
+
 	/* primary av */
 	qp_attr->ah_attr.sl = qpcb->service_level;
 
-- 
1.5.2

^ permalink raw reply related

* [PATCH 08/13] IB/ehca: Lock renaming, static initializers
From: Joachim Fenkes @ 2007-07-09 13:29 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

- Renamed all spinlock flags to "flags", matching the vast majority of kernel
  code.
- Moved hcall_lock into the only module it's used in.
- Replaced spin_lock_init() and friends with static initializers for
  global variables.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |    1 -
 drivers/infiniband/hw/ehca/ehca_cq.c      |   12 ++++++------
 drivers/infiniband/hw/ehca/ehca_main.c    |   18 ++++--------------
 drivers/infiniband/hw/ehca/ehca_qp.c      |    6 +++---
 drivers/infiniband/hw/ehca/ehca_reqs.c    |   24 ++++++++++++------------
 drivers/infiniband/hw/ehca/hcp_if.c       |    2 ++
 6 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 9d689ae..3550047 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -295,7 +295,6 @@ void ehca_cleanup_mrmw_cache(void);
 
 extern spinlock_t ehca_qp_idr_lock;
 extern spinlock_t ehca_cq_idr_lock;
-extern spinlock_t hcall_lock;
 extern struct idr ehca_qp_idr;
 extern struct idr ehca_cq_idr;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 67f0670..94bad27 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -56,11 +56,11 @@ int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
 {
 	unsigned int qp_num = qp->real_qp_num;
 	unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
-	unsigned long spl_flags;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cq->spinlock, spl_flags);
+	spin_lock_irqsave(&cq->spinlock, flags);
 	hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
-	spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&cq->spinlock, flags);
 
 	ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
 		 cq->cq_number, qp_num);
@@ -74,9 +74,9 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
 	unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
 	struct hlist_node *iter;
 	struct ehca_qp *qp;
-	unsigned long spl_flags;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cq->spinlock, spl_flags);
+	spin_lock_irqsave(&cq->spinlock, flags);
 	hlist_for_each(iter, &cq->qp_hashtab[key]) {
 		qp = hlist_entry(iter, struct ehca_qp, list_entries);
 		if (qp->real_qp_num == real_qp_num) {
@@ -88,7 +88,7 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&cq->spinlock, flags);
 	if (ret)
 		ehca_err(cq->ib_cq.device,
 			 "qp not found cq_num=%x real_qp_num=%x",
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 9bd749c..77db890 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -96,15 +96,13 @@ MODULE_PARM_DESC(static_rate,
 MODULE_PARM_DESC(scaling_code,
 		 "set scaling code (0: disabled/default, 1: enabled)");
 
-spinlock_t ehca_qp_idr_lock;
-spinlock_t ehca_cq_idr_lock;
-spinlock_t hcall_lock;
+DEFINE_SPINLOCK(ehca_qp_idr_lock);
+DEFINE_SPINLOCK(ehca_cq_idr_lock);
 DEFINE_IDR(ehca_qp_idr);
 DEFINE_IDR(ehca_cq_idr);
 
-
-static struct list_head shca_list; /* list of all registered ehcas */
-static spinlock_t shca_list_lock;
+static LIST_HEAD(shca_list); /* list of all registered ehcas */
+static DEFINE_SPINLOCK(shca_list_lock);
 
 static struct timer_list poll_eqs_timer;
 
@@ -864,14 +862,6 @@ int __init ehca_module_init(void)
 
 	printk(KERN_INFO "eHCA Infiniband Device Driver "
 	       "(Rel.: SVNEHCA_0023)\n");
-	idr_init(&ehca_qp_idr);
-	idr_init(&ehca_cq_idr);
-	spin_lock_init(&ehca_qp_idr_lock);
-	spin_lock_init(&ehca_cq_idr_lock);
-	spin_lock_init(&hcall_lock);
-
-	INIT_LIST_HEAD(&shca_list);
-	spin_lock_init(&shca_list_lock);
 
 	if ((ret = ehca_create_comp_pool())) {
 		ehca_gen_err("Cannot create comp pool.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 989f75e..ac4ff26 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -933,7 +933,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 	u64 h_ret;
 	int bad_wqe_cnt = 0;
 	int squeue_locked = 0;
-	unsigned long spl_flags = 0;
+	unsigned long flags = 0;
 
 	/* do query_qp to obtain current attr values */
 	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -1074,7 +1074,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 		if (!ibqp->uobject) {
 			struct ehca_wqe *wqe;
 			/* lock send queue */
-			spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+			spin_lock_irqsave(&my_qp->spinlock_s, flags);
 			squeue_locked = 1;
 			/* mark next free wqe */
 			wqe = (struct ehca_wqe*)
@@ -1360,7 +1360,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 
 modify_qp_exit2:
 	if (squeue_locked) { /* this means: sqe -> rts */
-		spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
+		spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 		my_qp->sqerr_purgeflag = 1;
 	}
 
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index b5664fa..73f0c06 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -363,10 +363,10 @@ int ehca_post_send(struct ib_qp *qp,
 	struct ehca_wqe *wqe_p;
 	int wqe_cnt = 0;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
 
 	/* LOCK the QUEUE */
-	spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+	spin_lock_irqsave(&my_qp->spinlock_s, flags);
 
 	/* loop processes list of send reqs */
 	for (cur_send_wr = send_wr; cur_send_wr != NULL;
@@ -408,7 +408,7 @@ int ehca_post_send(struct ib_qp *qp,
 
 post_send_exit0:
 	/* UNLOCK the QUEUE */
-	spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
+	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_sqa(my_qp, wqe_cnt);
 	return ret;
@@ -423,7 +423,7 @@ static int internal_post_recv(struct ehca_qp *my_qp,
 	struct ehca_wqe *wqe_p;
 	int wqe_cnt = 0;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
 
 	if (unlikely(!HAS_RQ(my_qp))) {
 		ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
@@ -432,7 +432,7 @@ static int internal_post_recv(struct ehca_qp *my_qp,
 	}
 
 	/* LOCK the QUEUE */
-	spin_lock_irqsave(&my_qp->spinlock_r, spl_flags);
+	spin_lock_irqsave(&my_qp->spinlock_r, flags);
 
 	/* loop processes list of send reqs */
 	for (cur_recv_wr = recv_wr; cur_recv_wr != NULL;
@@ -473,7 +473,7 @@ static int internal_post_recv(struct ehca_qp *my_qp,
 	} /* eof for cur_recv_wr */
 
 post_recv_exit0:
-	spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags);
+	spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_rqa(my_qp, wqe_cnt);
 	return ret;
@@ -536,7 +536,7 @@ poll_cq_one_read_cqe:
 	if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
 		struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number);
 		int purgeflag;
-		unsigned long spl_flags;
+		unsigned long flags;
 		if (!qp) {
 			ehca_err(cq->device, "cq_num=%x qp_num=%x "
 				 "could not find qp -> ignore cqe",
@@ -546,9 +546,9 @@ poll_cq_one_read_cqe:
 			/* ignore this purged cqe */
 			goto poll_cq_one_read_cqe;
 		}
-		spin_lock_irqsave(&qp->spinlock_s, spl_flags);
+		spin_lock_irqsave(&qp->spinlock_s, flags);
 		purgeflag = qp->sqerr_purgeflag;
-		spin_unlock_irqrestore(&qp->spinlock_s, spl_flags);
+		spin_unlock_irqrestore(&qp->spinlock_s, flags);
 
 		if (purgeflag) {
 			ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x "
@@ -633,7 +633,7 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
 	int nr;
 	struct ib_wc *current_wc = wc;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
 
 	if (num_entries < 1) {
 		ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
@@ -642,14 +642,14 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
 		goto poll_cq_exit0;
 	}
 
-	spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+	spin_lock_irqsave(&my_cq->spinlock, flags);
 	for (nr = 0; nr < num_entries; nr++) {
 		ret = ehca_poll_cq_one(cq, current_wc);
 		if (ret)
 			break;
 		current_wc++;
 	} /* eof for nr */
-	spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&my_cq->spinlock, flags);
 	if (ret == -EAGAIN  || !ret)
 		ret = nr;
 
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index b078377..5b927a6 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -81,6 +81,8 @@
 #define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
 #define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
 
+DEFINE_SPINLOCK(hcall_lock);
+
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
 	switch (longbusy_rc) {
-- 
1.5.2

^ permalink raw reply related

* [PATCH 09/13] IB/ehca: Refactor synchronization between completions and destroy_cq using atomic_t
From: Joachim Fenkes @ 2007-07-09 13:30 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

- ehca_cq.nr_events is made an atomic_t, eliminating a lot of locking.
- The CQ is removed from the CQ idr first now to make sure no more
  completions are scheduled on that CQ. The "wait for all completions to
  end" code becomes much simpler this way.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |    4 +-
 drivers/infiniband/hw/ehca/ehca_cq.c      |   26 +++++++-------------
 drivers/infiniband/hw/ehca/ehca_irq.c     |   36 +++++++++++++---------------
 drivers/infiniband/hw/ehca/ehca_irq.h     |    1 -
 drivers/infiniband/hw/ehca/ehca_tools.h   |    1 +
 5 files changed, 29 insertions(+), 39 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 3550047..8580f2a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -174,8 +174,8 @@ struct ehca_cq {
 	spinlock_t cb_lock;
 	struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
 	struct list_head entry;
-	u32 nr_callbacks; /* #events assigned to cpu by scaling code */
-	u32 nr_events;    /* #events seen */
+	u32 nr_callbacks;   /* #events assigned to cpu by scaling code */
+	atomic_t nr_events; /* #events seen */
 	wait_queue_head_t wait_completion;
 	spinlock_t task_lock;
 	u32 ownpid;
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 94bad27..3729997 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 	spin_lock_init(&my_cq->spinlock);
 	spin_lock_init(&my_cq->cb_lock);
 	spin_lock_init(&my_cq->task_lock);
+	atomic_set(&my_cq->nr_events, 0);
 	init_waitqueue_head(&my_cq->wait_completion);
 	my_cq->ownpid = current->tgid;
 
@@ -303,16 +304,6 @@ create_cq_exit1:
 	return cq;
 }
 
-static int get_cq_nr_events(struct ehca_cq *my_cq)
-{
-	int ret;
-	unsigned long flags;
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-	ret = my_cq->nr_events;
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-	return ret;
-}
-
 int ehca_destroy_cq(struct ib_cq *cq)
 {
 	u64 h_ret;
@@ -339,17 +330,18 @@ int ehca_destroy_cq(struct ib_cq *cq)
 		}
 	}
 
+	/*
+	 * remove the CQ from the idr first to make sure
+	 * no more interrupt tasklets will touch this CQ
+	 */
 	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-	while (my_cq->nr_events) {
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-		wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-		/* recheck nr_events to assure no cqe has just arrived */
-	}
-
 	idr_remove(&ehca_cq_idr, my_cq->token);
 	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
+	/* now wait until all pending events have completed */
+	wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
+
+	/* nobody's using our CQ any longer -- we can destroy it */
 	h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
 	if (h_ret == H_R_STATE) {
 		/* cq in err: read err data and destroy it forcibly */
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 100329b..3e790a3 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -5,6 +5,8 @@
  *
  *  Authors: Heiko J Schick <schickhj@de.ibm.com>
  *           Khadija Souissi <souissi@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -212,6 +214,8 @@ static void cq_event_callback(struct ehca_shca *shca,
 
 	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
 	cq = idr_find(&ehca_cq_idr, token);
+	if (cq)
+		atomic_inc(&cq->nr_events);
 	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 	if (!cq)
@@ -219,6 +223,9 @@ static void cq_event_callback(struct ehca_shca *shca,
 
 	ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
 
+	if (atomic_dec_and_test(&cq->nr_events))
+		wake_up(&cq->wait_completion);
+
 	return;
 }
 
@@ -414,25 +421,22 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 		token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
 		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
 		cq = idr_find(&ehca_cq_idr, token);
+		if (cq)
+			atomic_inc(&cq->nr_events);
+		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		if (cq == NULL) {
-			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 			ehca_err(&shca->ib_device,
 				 "Invalid eqe for non-existing cq token=%x",
 				 token);
 			return;
 		}
 		reset_eq_pending(cq);
-		cq->nr_events++;
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		if (ehca_scaling_code)
 			queue_comp_task(cq);
 		else {
 			comp_event_callback(cq);
-			spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-			cq->nr_events--;
-			if (!cq->nr_events)
+			if (atomic_dec_and_test(&cq->nr_events))
 				wake_up(&cq->wait_completion);
-			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		}
 	} else {
 		ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -478,15 +482,15 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 			token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
 			spin_lock(&ehca_cq_idr_lock);
 			eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+			if (eqe_cache[eqe_cnt].cq)
+				atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
+			spin_unlock(&ehca_cq_idr_lock);
 			if (!eqe_cache[eqe_cnt].cq) {
-				spin_unlock(&ehca_cq_idr_lock);
 				ehca_err(&shca->ib_device,
 					 "Invalid eqe for non-existing cq "
 					 "token=%x", token);
 				continue;
 			}
-			eqe_cache[eqe_cnt].cq->nr_events++;
-			spin_unlock(&ehca_cq_idr_lock);
 		} else
 			eqe_cache[eqe_cnt].cq = NULL;
 		eqe_cnt++;
@@ -517,11 +521,8 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 			else {
 				struct ehca_cq *cq = eq->eqe_cache[i].cq;
 				comp_event_callback(cq);
-				spin_lock(&ehca_cq_idr_lock);
-				cq->nr_events--;
-				if (!cq->nr_events)
+				if (atomic_dec_and_test(&cq->nr_events))
 					wake_up(&cq->wait_completion);
-				spin_unlock(&ehca_cq_idr_lock);
 			}
 		} else {
 			ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -621,13 +622,10 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
 	while (!list_empty(&cct->cq_list)) {
 		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 		spin_unlock_irqrestore(&cct->task_lock, flags);
-		comp_event_callback(cq);
 
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-		cq->nr_events--;
-		if (!cq->nr_events)
+		comp_event_callback(cq);
+		if (atomic_dec_and_test(&cq->nr_events))
 			wake_up(&cq->wait_completion);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 		spin_lock_irqsave(&cct->task_lock, flags);
 		spin_lock(&cq->task_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 6ed06ee..3346cb0 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -47,7 +47,6 @@ struct ehca_shca;
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
 
 int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 973c4b5..03b185f 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -59,6 +59,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 
+#include <asm/atomic.h>
 #include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
-- 
1.5.2

^ permalink raw reply related

* [PATCH 10/13] IB/ehca: Change idr spinlocks into rwlocks
From: Joachim Fenkes @ 2007-07-09 13:31 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

This eliminates lock contention among IRQs as well as the need to disable
IRQs around idr_find, because there are no IRQ writers.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |    4 ++--
 drivers/infiniband/hw/ehca/ehca_cq.c      |   12 ++++++------
 drivers/infiniband/hw/ehca/ehca_irq.c     |   19 ++++++++-----------
 drivers/infiniband/hw/ehca/ehca_main.c    |    4 ++--
 drivers/infiniband/hw/ehca/ehca_qp.c      |   12 ++++++------
 drivers/infiniband/hw/ehca/ehca_uverbs.c  |    9 ++++-----
 6 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 8580f2a..f1e0db2 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -293,8 +293,8 @@ void ehca_cleanup_av_cache(void);
 int ehca_init_mrmw_cache(void);
 void ehca_cleanup_mrmw_cache(void);
 
-extern spinlock_t ehca_qp_idr_lock;
-extern spinlock_t ehca_cq_idr_lock;
+extern rwlock_t ehca_qp_idr_lock;
+extern rwlock_t ehca_cq_idr_lock;
 extern struct idr ehca_qp_idr;
 extern struct idr ehca_cq_idr;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 3729997..01d4a14 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -163,9 +163,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			goto create_cq_exit1;
 		}
 
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		write_lock_irqsave(&ehca_cq_idr_lock, flags);
 		ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 	} while (ret == -EAGAIN);
 
@@ -294,9 +294,9 @@ create_cq_exit3:
 			 "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
 
 create_cq_exit2:
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	write_lock_irqsave(&ehca_cq_idr_lock, flags);
 	idr_remove(&ehca_cq_idr, my_cq->token);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 create_cq_exit1:
 	kmem_cache_free(cq_cache, my_cq);
@@ -334,9 +334,9 @@ int ehca_destroy_cq(struct ib_cq *cq)
 	 * remove the CQ from the idr first to make sure
 	 * no more interrupt tasklets will touch this CQ
 	 */
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	write_lock_irqsave(&ehca_cq_idr_lock, flags);
 	idr_remove(&ehca_cq_idr, my_cq->token);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 	/* now wait until all pending events have completed */
 	wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 3e790a3..02b73c8 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -180,12 +180,11 @@ static void qp_event_callback(struct ehca_shca *shca,
 {
 	struct ib_event event;
 	struct ehca_qp *qp;
-	unsigned long flags;
 	u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
 
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	read_lock(&ehca_qp_idr_lock);
 	qp = idr_find(&ehca_qp_idr, token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	read_unlock(&ehca_qp_idr_lock);
 
 
 	if (!qp)
@@ -209,14 +208,13 @@ static void cq_event_callback(struct ehca_shca *shca,
 			      u64 eqe)
 {
 	struct ehca_cq *cq;
-	unsigned long flags;
 	u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
 
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	read_lock(&ehca_cq_idr_lock);
 	cq = idr_find(&ehca_cq_idr, token);
 	if (cq)
 		atomic_inc(&cq->nr_events);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	read_unlock(&ehca_cq_idr_lock);
 
 	if (!cq)
 		return;
@@ -411,7 +409,6 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 {
 	u64 eqe_value;
 	u32 token;
-	unsigned long flags;
 	struct ehca_cq *cq;
 
 	eqe_value = eqe->entry;
@@ -419,11 +416,11 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 	if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
 		ehca_dbg(&shca->ib_device, "Got completion event");
 		token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		read_lock(&ehca_cq_idr_lock);
 		cq = idr_find(&ehca_cq_idr, token);
 		if (cq)
 			atomic_inc(&cq->nr_events);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		read_unlock(&ehca_cq_idr_lock);
 		if (cq == NULL) {
 			ehca_err(&shca->ib_device,
 				 "Invalid eqe for non-existing cq token=%x",
@@ -480,11 +477,11 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 		eqe_value = eqe_cache[eqe_cnt].eqe->entry;
 		if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
 			token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-			spin_lock(&ehca_cq_idr_lock);
+			read_lock(&ehca_cq_idr_lock);
 			eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
 			if (eqe_cache[eqe_cnt].cq)
 				atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
-			spin_unlock(&ehca_cq_idr_lock);
+			read_unlock(&ehca_cq_idr_lock);
 			if (!eqe_cache[eqe_cnt].cq) {
 				ehca_err(&shca->ib_device,
 					 "Invalid eqe for non-existing cq "
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 77db890..e58e821 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -96,8 +96,8 @@ MODULE_PARM_DESC(static_rate,
 MODULE_PARM_DESC(scaling_code,
 		 "set scaling code (0: disabled/default, 1: enabled)");
 
-DEFINE_SPINLOCK(ehca_qp_idr_lock);
-DEFINE_SPINLOCK(ehca_cq_idr_lock);
+DEFINE_RWLOCK(ehca_qp_idr_lock);
+DEFINE_RWLOCK(ehca_cq_idr_lock);
 DEFINE_IDR(ehca_qp_idr);
 DEFINE_IDR(ehca_cq_idr);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index ac4ff26..7452ef4 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -512,9 +512,9 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
 			goto create_qp_exit0;
 		}
 
-		spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+		write_lock_irqsave(&ehca_qp_idr_lock, flags);
 		ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
-		spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+		write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 	} while (ret == -EAGAIN);
 
@@ -733,9 +733,9 @@ create_qp_exit2:
 	hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 
 create_qp_exit1:
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	write_lock_irqsave(&ehca_qp_idr_lock, flags);
 	idr_remove(&ehca_qp_idr, my_qp->token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 create_qp_exit0:
 	kmem_cache_free(qp_cache, my_qp);
@@ -1706,9 +1706,9 @@ int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
 		}
 	}
 
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	write_lock_irqsave(&ehca_qp_idr_lock, flags);
 	idr_remove(&ehca_qp_idr, my_qp->token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 	h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 	if (h_ret != H_SUCCESS) {
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index d8fe37d..3031b3b 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -253,7 +253,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 	u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
 	u32 cur_pid = current->tgid;
 	u32 ret;
-	unsigned long flags;
 	struct ehca_cq *cq;
 	struct ehca_qp *qp;
 	struct ehca_pd *pd;
@@ -261,9 +260,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 
 	switch (q_type) {
 	case  1: /* CQ */
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		read_lock(&ehca_cq_idr_lock);
 		cq = idr_find(&ehca_cq_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		read_unlock(&ehca_cq_idr_lock);
 
 		/* make sure this mmap really belongs to the authorized user */
 		if (!cq)
@@ -289,9 +288,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 		break;
 
 	case 2: /* QP */
-		spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+		read_lock(&ehca_qp_idr_lock);
 		qp = idr_find(&ehca_qp_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+		read_unlock(&ehca_qp_idr_lock);
 
 		/* make sure this mmap really belongs to the authorized user */
 		if (!qp)
-- 
1.5.2

^ permalink raw reply related

* [PATCH 11/13] IB/ehca: return QP pointer in poll_cq(), add two unlikely() statements
From: Joachim Fenkes @ 2007-07-09 13:31 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_reqs.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 73f0c06..fd3ba22 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -517,6 +517,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
 	int ret = 0;
 	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
 	struct ehca_cqe *cqe;
+	struct ehca_qp *my_qp;
 	int cqe_count = 0;
 
 poll_cq_one_read_cqe:
@@ -568,7 +569,7 @@ poll_cq_one_read_cqe:
 	}
 
 	/* tracing cqe */
-	if (ehca_debug_level) {
+	if (unlikely(ehca_debug_level)) {
 		ehca_dbg(cq->device,
 			 "Received COMPLETION ehca_cq=%p cq_num=%x -----",
 			 my_cq, my_cq->cq_number);
@@ -602,7 +603,11 @@ poll_cq_one_read_cqe:
 	} else
 		wc->status = IB_WC_SUCCESS;
 
-	wc->qp = NULL;
+	read_lock(&ehca_qp_idr_lock);
+	my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+	wc->qp = &my_qp->ib_qp;
+	read_unlock(&ehca_qp_idr_lock);
+
 	wc->byte_len = cqe->nr_bytes_transferred;
 	wc->pkey_index = cqe->pkey_index;
 	wc->slid = cqe->rlid;
@@ -612,7 +617,7 @@ poll_cq_one_read_cqe:
 	wc->imm_data = cpu_to_be32(cqe->immediate_data);
 	wc->sl = cqe->service_level;
 
-	if (wc->status != IB_WC_SUCCESS)
+	if (unlikely(wc->status != IB_WC_SUCCESS))
 		ehca_dbg(cq->device,
 			 "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
 			 "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
-- 
1.5.2

^ permalink raw reply related

* [PATCH 12/13] IB/ehca: notify consumers of LID/PKEY/SM changes after nondisruptive events
From: Joachim Fenkes @ 2007-07-09 13:32 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

When firmware reports a nondisruptive port configuration change event,
previous versions of the eHCA driver didn't forward the event to consumers
like IPoIB. Add code that determines the type of configuration change by
comparing old and new port attributes and reports it.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |    6 ++
 drivers/infiniband/hw/ehca/ehca_hca.c     |   34 +++++++++++
 drivers/infiniband/hw/ehca/ehca_irq.c     |   89 +++++++++++++++++++----------
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |    3 +
 4 files changed, 101 insertions(+), 31 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index f1e0db2..daf823e 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -87,11 +87,17 @@ struct ehca_eq {
 	struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
 };
 
+struct ehca_sma_attr {
+	u16 lid, lmc, sm_sl, sm_lid;
+	u16 pkey_tbl_len, pkeys[16];
+};
+
 struct ehca_sport {
 	struct ib_cq *ibcq_aqp1;
 	struct ib_qp *ibqp_aqp1;
 	enum ib_rate  rate;
 	enum ib_port_state port_state;
+	struct ehca_sma_attr saved_attr;
 };
 
 struct ehca_shca {
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index b310de5..bbd3c6a 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -193,6 +193,40 @@ query_port1:
 	return ret;
 }
 
+int ehca_query_sma_attr(struct ehca_shca *shca,
+			u8 port, struct ehca_sma_attr *attr)
+{
+	int ret = 0;
+	struct hipz_query_port *rblock;
+
+	rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+	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 query_sma_attr1;
+	}
+
+	memset(attr, 0, sizeof(struct ehca_sma_attr));
+
+	attr->lid    = rblock->lid;
+	attr->lmc    = rblock->lmc;
+	attr->sm_sl  = rblock->sm_sl;
+	attr->sm_lid = rblock->sm_lid;
+
+	attr->pkey_tbl_len = rblock->pkey_tbl_len;
+	memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
+
+query_sma_attr1:
+	ehca_free_fw_ctrlblock(rblock);
+
+	return ret;
+}
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 {
 	int ret = 0;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 02b73c8..96eba38 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -61,6 +61,7 @@
 #define NEQE_EVENT_CODE        EHCA_BMASK_IBM(2,7)
 #define NEQE_PORT_NUMBER       EHCA_BMASK_IBM(8,15)
 #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
+#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16,16)
 
 #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
 #define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
@@ -286,30 +287,61 @@ static void parse_identifier(struct ehca_shca *shca, u64 eqe)
 	return;
 }
 
-static void parse_ec(struct ehca_shca *shca, u64 eqe)
+static void dispatch_port_event(struct ehca_shca *shca, int port_num,
+				enum ib_event_type type, const char *msg)
 {
 	struct ib_event event;
+
+	ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
+	event.device = &shca->ib_device;
+	event.event = type;
+	event.element.port_num = port_num;
+	ib_dispatch_event(&event);
+}
+
+static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
+{
+	struct ehca_sma_attr  new_attr;
+	struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
+
+	ehca_query_sma_attr(shca, port_num, &new_attr);
+
+	if (new_attr.sm_sl  != old_attr->sm_sl ||
+	    new_attr.sm_lid != old_attr->sm_lid)
+		dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
+				    "SM changed");
+
+	if (new_attr.lid != old_attr->lid ||
+	    new_attr.lmc != old_attr->lmc)
+		dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
+				    "LID changed");
+
+	if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
+	    memcmp(new_attr.pkeys, old_attr->pkeys,
+		   sizeof(u16) * new_attr.pkey_tbl_len))
+		dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
+				    "P_Key changed");
+
+	*old_attr = new_attr;
+}
+
+static void parse_ec(struct ehca_shca *shca, u64 eqe)
+{
 	u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
 	u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
 
 	switch (ec) {
 	case 0x30: /* port availability change */
 		if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-			ehca_info(&shca->ib_device,
-				  "port %x is active.", port);
-			event.device = &shca->ib_device;
-			event.event = IB_EVENT_PORT_ACTIVE;
-			event.element.port_num = port;
 			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-			ib_dispatch_event(&event);
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+					    "is active");
+			ehca_query_sma_attr(shca, port,
+					    &shca->sport[port - 1].saved_attr);
 		} else {
-			ehca_info(&shca->ib_device,
-				  "port %x is inactive.", port);
-			event.device = &shca->ib_device;
-			event.event = IB_EVENT_PORT_ERR;
-			event.element.port_num = port;
 			shca->sport[port - 1].port_state = IB_PORT_DOWN;
-			ib_dispatch_event(&event);
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+					    "is inactive");
 		}
 		break;
 	case 0x31:
@@ -317,24 +349,19 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
 		 * disruptive change is caused by
 		 * LID, PKEY or SM change
 		 */
-		ehca_warn(&shca->ib_device,
-			  "disruptive port %x configuration change", port);
-
-		ehca_info(&shca->ib_device,
-			  "port %x is inactive.", port);
-		event.device = &shca->ib_device;
-		event.event = IB_EVENT_PORT_ERR;
-		event.element.port_num = port;
-		shca->sport[port - 1].port_state = IB_PORT_DOWN;
-		ib_dispatch_event(&event);
-
-		ehca_info(&shca->ib_device,
-			  "port %x is active.", port);
-		event.device = &shca->ib_device;
-		event.event = IB_EVENT_PORT_ACTIVE;
-		event.element.port_num = port;
-		shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-		ib_dispatch_event(&event);
+		if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
+			ehca_warn(&shca->ib_device, "disruptive port "
+				  "%d configuration change", port);
+
+			shca->sport[port - 1].port_state = IB_PORT_DOWN;
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+					    "is inactive");
+
+			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+					    "is active");
+		} else
+			notify_port_conf_change(shca, port);
 		break;
 	case 0x32: /* adapter malfunction */
 		ehca_err(&shca->ib_device, "Adapter malfunction.");
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index fd84a80..77aeca6 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -49,6 +49,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props);
 int ehca_query_port(struct ib_device *ibdev, u8 port,
 		    struct ib_port_attr *props);
 
+int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
+			struct ehca_sma_attr *attr);
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
 
 int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
-- 
1.5.2

^ permalink raw reply related

* [PATCH 13/13] IB/ehca: Improve latency by unlocking the SQ/RQ after triggering the hardware
From: Joachim Fenkes @ 2007-07-09 13:33 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch
In-Reply-To: <200707091502.22407.fenkes@de.ibm.com>

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_reqs.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index fd3ba22..61da65e 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -407,10 +407,9 @@ int ehca_post_send(struct ib_qp *qp,
 	} /* eof for cur_send_wr */
 
 post_send_exit0:
-	/* UNLOCK the QUEUE */
-	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_sqa(my_qp, wqe_cnt);
+	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 	return ret;
 }
 
@@ -473,9 +472,9 @@ static int internal_post_recv(struct ehca_qp *my_qp,
 	} /* eof for cur_recv_wr */
 
 post_recv_exit0:
-	spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_rqa(my_qp, wqe_cnt);
+	spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
 	return ret;
 }
 
-- 
1.5.2

^ permalink raw reply related

* Re: ARCH=ppc vs ARCH=powerpc
From: Mark Fortescue @ 2007-07-09 14:33 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-embedded
In-Reply-To: <200707090234.14851.arnd@arndb.de>

Hi All,

I am currently trying to identify an anoying feature of linux on my 
sparc32 systems but I will do some work on the ppc -> powerpc migration 
as soon as I have exauhsted my current avenues of investiation on the 
sparc32 issue.

Regards
 	Mark Fortescue.

On Mon, 9 Jul 2007, Arnd Bergmann wrote:

> On Friday 06 July 2007, Mark Fortescue wrote:
>> For me, the requirement is to keep support for the cards indicated in
>> arch/ppc/config/xxx_defconfig (as I have one that I might what to use with
>> linux) in the same way as they are supported in ARCH=ppc.
>
> The one thing that is holding up the transition to arch/powerpc is lack
> of people with access to the respective boards. If you have one board
> that you care about, it would be good if you look into getting it moved
> over. Tell us if you have problems doing so. It shouldn't be all that
> hard any more, and if it is, maybe some documentation is missing.
>
>> I have just made some tweeks to get ARCH=ppc building for me but I still
>> need to sort out what is required to get around *** Error: Headers not
>> exportable for this architecture (ppc).
>
> You should simply install the headers with ARCH=powerc, even when the
> kernel is built with ARCH=ppc. From the user space point of view, there
> is only one set of headers.
>
> 	Arnd <><
>

^ permalink raw reply

* Re: [PATCH 2/5] Add legacy devices to mpc8641_hpcn.dts
From: Segher Boessenkool @ 2007-07-09 14:43 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linuxppc-dev
In-Reply-To: <46922D86.5040305@ru.mvista.com>

>>>   Yet it's kinda accepted years ago, see:
>
>>> http://playground.sun.com/1275/proposals/Closed/Accepted/381-it.txt
>
>> That's not a published recommendation or anything like that.
>
>    There's also this document with a status of "unapproved draft":
>
> http://playground.sun.com/1275/bindings/devices/html/8042.html
>
>    So, all this never got final approval? Somewhat confusing (well,  
> what one could expect from OF? :-)

I think this 8042 thing became part of the CHRP binding.  There
never was a (published) x86 binding btw.  So for our current
purposes (flat device tree) I recommend we just do the minimal
sane thing, i.e., no device_type and some good "compatible" entry.


Segher

^ permalink raw reply

* Re: 2.4/2.6/ppc/powerpc/8245/8347e
From: Marc Leeman @ 2007-07-09 15:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070629145936.GL2660@chiana.homelinux.org>

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

> More platforms and higher bitrate tests (I've left the previous post in
> comment):

I finally was able to figure out the culprid:

CONFIG_SLOB=y

instead of 

CONFIG_SLAB=y

--------
CONFIG_SLAB:

Disabling this replaces the advanced SLAB allocator and
kmalloc support with the drastically simpler SLOB allocator.
SLOB is more space efficient but does not scale well and is
more susceptible to fragmentation. 
--------

I was expecting a lower DMM performance but wasn't expecting such a
drain on kernel/network load.

The original reason for this change was a fixed flashmap and a increased
2.6 kernel that didn't fit in this region (backwards compatible).

-- 
  greetz, marc
I feel like I had a spiritual enema.
	Jool - Losing Time
chiana 2.6.18-4-ixp4xx #1 Tue Mar 27 18:01:56 BST 2007 GNU/Linux

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

^ permalink raw reply

* Re: [PATCH] i2c-mpc: work around missing-9th-clock-pulse bug
From: Grant Likely @ 2007-07-09 15:53 UTC (permalink / raw)
  To: Domen Puncer; +Cc: khali, i2c, linuxppc-embedded
In-Reply-To: <20070709071955.GD4186@moe.telargo.com>

On 7/9/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Work around a problem reported on:
> http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
> Without this patch I2C on mpc5200 becomes unusable after a while.
> Tested on mpc5200 based boards by Matthias and me.
>
> Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
> ===================================================================
> --- work-powerpc.git.orig/drivers/i2c/busses/i2c-mpc.c
> +++ work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
> @@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
>  static void mpc_i2c_stop(struct mpc_i2c *i2c)
>  {
>         writeccr(i2c, CCR_MEN);
> +       mb();
> +       writeccr(i2c, 0);
> +       mb();
>  }

Are the mb() calls necessary?  The writeccr path includes eieio; is
that not sufficient?

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH] mpc52xx: sparse fixes
From: Grant Likely @ 2007-07-09 15:58 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded
In-Reply-To: <20070709075203.GF4186@moe.telargo.com>

On 7/9/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> sparse caught these static functions / __iomem annotations
> under arch/powerpc/platform/52xx/
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

>
> ---
> Reposting, adding tnt to Cc, and requesting inclusion.
> The patch is pretty much harmless :-)
>
>
>  arch/powerpc/platforms/52xx/efika.c      |    4 ++--
>  arch/powerpc/platforms/52xx/lite5200.c   |    2 +-
>  arch/powerpc/platforms/52xx/mpc52xx_pm.c |    8 ++++----
>  3 files changed, 7 insertions(+), 7 deletions(-)
>
> Index: work-powerpc.git/arch/powerpc/platforms/52xx/efika.c
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/platforms/52xx/efika.c
> +++ work-powerpc.git/arch/powerpc/platforms/52xx/efika.c
> @@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = {
>  };
>
>
> -void __init efika_pcisetup(void)
> +static void __init efika_pcisetup(void)
>  {
>         const int *bus_range;
>         int len;
> @@ -145,7 +145,7 @@ void __init efika_pcisetup(void)
>  }
>
>  #else
> -void __init efika_pcisetup(void)
> +static void __init efika_pcisetup(void)
>  {}
>  #endif
>
> Index: work-powerpc.git/arch/powerpc/platforms/52xx/lite5200.c
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/platforms/52xx/lite5200.c
> +++ work-powerpc.git/arch/powerpc/platforms/52xx/lite5200.c
> @@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(v
>
>  }
>
> -void lite5200_show_cpuinfo(struct seq_file *m)
> +static void lite5200_show_cpuinfo(struct seq_file *m)
>  {
>         struct device_node* np = of_find_all_nodes(NULL);
>         const char *model = NULL;
> Index: work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/platforms/52xx/mpc52xx_pm.c
> +++ work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
> @@ -9,8 +9,8 @@
>
>
>  /* these are defined in mpc52xx_sleep.S, and only used here */
> -extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
> -               struct mpc52xx_cdm *, struct mpc52xx_intr *);
> +extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
> +               struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
>  extern void mpc52xx_ds_sram(void);
>  extern const long mpc52xx_ds_sram_size;
>  extern void mpc52xx_ds_cached(void);
> @@ -21,7 +21,7 @@ static void __iomem *sdram;
>  static struct mpc52xx_cdm __iomem *cdm;
>  static struct mpc52xx_intr __iomem *intr;
>  static struct mpc52xx_gpio_wkup __iomem *gpiow;
> -static void *sram;
> +static void __iomem *sram;
>  static int sram_size;
>
>  struct mpc52xx_suspend mpc52xx_suspend;
> @@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t sta
>         u32 clk_enables;
>         u32 msr, hid0;
>         u32 intr_main_mask;
> -       void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
> +       void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
>         unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
>         char saved_0x500[mpc52xx_ds_cached_size];
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH] Add USB support to mpc8349-mitx board port
From: Grant Likely @ 2007-07-09 17:03 UTC (permalink / raw)
  To: John Rigby; +Cc: Linuxppc-embedded
In-Reply-To: <4b73d43f0707082055y2b96fa53td55d6b381b6fb0ef@mail.gmail.com>

On 7/8/07, John Rigby <jcrigby@gmail.com> wrote:
> I see your point, I agree the two layers of glue is bad.  But this means
> the double code is spread across many drivers instead of being in one
> place (fsl_soc.c).

???  I don't understand what you mean.  Are you saying that it's
better to have all the OF bindings in one place (fsl_soc.c) instead of
with each individual driver?

Cheers,
g.


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [patch 01/35] pasemi: rename platform
From: Olof Johansson @ 2007-07-09 17:19 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linuxppc-dev
In-Reply-To: <20070709172302.149e3fe0.sfr@canb.auug.org.au>

On Mon, Jul 09, 2007 at 05:23:02PM +1000, Stephen Rothwell wrote:
> On Sun, 8 Jul 2007 19:18:35 -0500 Olof Johansson <olof@lixom.net> wrote:
> >
> > On Mon, Jul 09, 2007 at 09:52:59AM +1000, Stephen Rothwell wrote:
> > > 
> > > This should also fix a problem further up in that file (in
> > > pasemi_publish_devices) where we check for "machine_is(pasemi)".
> > 
> > Yup, that's how I discovered the machine name being less than intuitive.
> 
> So it is worth noting in the chnge log.

Yeah sure, but not enough to repost the patch. The only problem it causes
is that a driver introduced a little earlier (but in the same release)
won't probe until this is applied.


-Olof

^ permalink raw reply

* Re: [patch 01/35] pasemi: rename platform
From: Olof Johansson @ 2007-07-09 17:21 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linuxppc-dev
In-Reply-To: <20070709171925.GA7083@lixom.net>

On Mon, Jul 09, 2007 at 12:19:26PM -0500, Olof Johansson wrote:
> Yeah sure, but not enough to repost the patch. The only problem it causes
> is that a driver introduced a little earlier (but in the same release)
> won't probe until this is applied.

Well, the SDC drivers are affected too (RNG, cpufreq). Still, there aren't
enough mainline users of the platform for it to be a concern at this time.


-Olof

^ permalink raw reply

* [PATCH] Infinite loop/always true check possible with unsigned counter.
From: Manish Ahuja @ 2007-07-09 17:31 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: ppc-dev

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

Fix to correct a possible infinite loop or an always true check when the 
unsigned long counter "i" is used in
lmb_add_region() in the following for loop:

for (i = rgn->cnt-1; i >= 0; i--)

Signed-off-by: Manish Ahuja <ahuja@us.ibm.com>


[-- Attachment #2: unsigned --]
[-- Type: text/plain, Size: 698 bytes --]

---
 arch/powerpc/mm/lmb.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: 2.6.22-rc4/arch/powerpc/mm/lmb.c
===================================================================
--- 2.6.22-rc4.orig/arch/powerpc/mm/lmb.c	2007-06-11 21:10:46.000000000 -0500
+++ 2.6.22-rc4/arch/powerpc/mm/lmb.c	2007-07-06 21:47:40.000000000 -0500
@@ -138,8 +138,8 @@ void __init lmb_analyze(void)
 static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
 				  unsigned long size)
 {
-	unsigned long i, coalesced = 0;
-	long adjacent;
+	unsigned long coalesced = 0;
+	long adjacent, i;
 
 	/* First try and coalesce this LMB with another. */
 	for (i=0; i < rgn->cnt; i++) {

^ permalink raw reply

* Re: [PATCH] [POWERPC] check for NULL ppc_md.init_IRQ() before calling
From: Sonny Rao @ 2007-07-09 17:31 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, paulus, miltonm
In-Reply-To: <20070706091634.GA19238@kevlar.boston.burdell.org>

On Fri, Jul 06, 2007 at 05:16:34AM -0400, Sonny Rao wrote:
> On Thu, Jul 05, 2007 at 08:37:34AM -0500, Olof Johansson wrote:
> > On Sun, Jul 01, 2007 at 08:49:37PM -0400, Sonny Rao wrote:
> > > The pseries platform does not have a default function for init_IRQ and
> > > does not install one if it doesn't find or doesn't recognize an
> > > interrupt controller in the device tree.  Currently, the kernel dies
> > > when it tries to call the NULL init_IRQ() function.  Clean that up.
> > 
> > Doesn't it make more sense to make init_IRQ() check that the pointer is
> > set instead? That'll work for more platforms than just pseries.
> 
> Yeah, that might be the simplest way.  The only reason I can think of
> to do it this way is that (I think) every single other platform in
> arch/powerpc statically initializes init_IRQ, with pseries being the
> oddball.  It doesn't matter much to me, so I can post another patch in a
> bit.

Check to make sure ppc_md.init_IRQ exists before calling it.

Signed-off-by: Sonny Rao <sonny@burdell.org>

--- linux/arch/powerpc/kernel/irq.c~orig 2007-07-09 12:46:58.000000000 -0500
+++ linux/arch/powerpc/kernel/irq.c 2007-07-09 12:47:07.000000000 -0500
@@ -337,8 +337,8 @@ void do_IRQ(struct pt_regs *regs)
 
 void __init init_IRQ(void)
 {
-
-	ppc_md.init_IRQ();
+	if (ppc_md.init_IRQ)
+		ppc_md.init_IRQ();
 #ifdef CONFIG_PPC64
 	irq_ctx_init();
 #endif

^ permalink raw reply

* [PATCH][POWERPC] document ipic level/sense info
From: Stuart Yoder @ 2007-07-09 18:20 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev


document level and sense information for the Freescale
IPIC interrupt controller


Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
---
 Documentation/powerpc/booting-without-of.txt |   20 +++++++++++++++++++-
 1 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index c169299..d26e2bd 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -50,13 +50,14 @@ Table of Contents
       g) Freescale SOC SEC Security Engines
       h) Board Control and Status (BCSR)
       i) Freescale QUICC Engine module (QE)
-      g) Flash chip nodes
+      j) Flash chip nodes
 
   VII - Specifying interrupt information for devices
     1) interrupts property
     2) interrupt-parent property
     3) OpenPIC Interrupt Controllers
     4) ISA Interrupt Controllers
+    5) IPIC Interrupt Controllers
 
   Appendix A - Sample SOC node for MPC8540
 
@@ -1878,6 +1879,23 @@ encodings listed below:
 	2 =  high to low edge sensitive type enabled
 	3 =  low to high edge sensitive type enabled
 
+5) Freescale IPIC Interrupt Controllers
+---------------------------------------
+
+IPIC interrupt controllers are specific to Freescale 83xx
+SOCs.  Two cells are required to encode interrupt information.
+The first cell defines the interrupt number.  The second cell
+defines the sense and level information.
+
+Sense and level information follows the Linux convention
+(specified in include/linux/interrupt.h) and should be encoded
+as follows:
+
+	1 =  low to high edge sensitive type enabled
+	2 =  high to low edge sensitive type enabled
+	4 =  active high level sensitive type enabled
+	8 =  active low level sensitive type enabled
+
 
 Appendix A - Sample SOC node for MPC8540
 ========================================
-- 
1.5.0.3

^ permalink raw reply related

* Re: [PATCH] Infinite loop/always true check possible with unsigned counter.
From: Manish Ahuja @ 2007-07-09 19:03 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: ppc-dev
In-Reply-To: <469270F3.4070206@austin.ibm.com>

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

Repost to fix my email id.

Fix to correct a possible infinite loop or an always true check when the 
unsigned long counter "i" is used in
lmb_add_region() in the following for loop:

for (i = rgn->cnt-1; i >= 0; i--)

Signed-off-by: Manish Ahuja <ahuja@austin.ibm.com>



[-- Attachment #2: unsigned --]
[-- Type: text/plain, Size: 698 bytes --]

---
 arch/powerpc/mm/lmb.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: 2.6.22-rc4/arch/powerpc/mm/lmb.c
===================================================================
--- 2.6.22-rc4.orig/arch/powerpc/mm/lmb.c	2007-06-11 21:10:46.000000000 -0500
+++ 2.6.22-rc4/arch/powerpc/mm/lmb.c	2007-07-06 21:47:40.000000000 -0500
@@ -138,8 +138,8 @@ void __init lmb_analyze(void)
 static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
 				  unsigned long size)
 {
-	unsigned long i, coalesced = 0;
-	long adjacent;
+	unsigned long coalesced = 0;
+	long adjacent, i;
 
 	/* First try and coalesce this LMB with another. */
 	for (i=0; i < rgn->cnt; i++) {

^ permalink raw reply

* Re: 2.4/2.6/ppc/powerpc/8245/8347e
From: Linas Vepstas @ 2007-07-09 19:56 UTC (permalink / raw)
  To: Marc Leeman; +Cc: linuxppc-dev
In-Reply-To: <20070709154723.GD2660@chiana.homelinux.org>

On Mon, Jul 09, 2007 at 05:47:23PM +0200, Marc Leeman wrote:
> 
> Disabling this replaces the advanced SLAB allocator and
> kmalloc support with the drastically simpler SLOB allocator.
> SLOB is more space efficient but does not scale well and is
> more susceptible to fragmentation. 
> --------
> 
> I was expecting a lower DMM performance but wasn't expecting such a
> drain on kernel/network load.

OK, to be clear: you seem to be saying that using the SLOB instead
of the SLAB allocator results in such terrible memory fragmentation
that network performance is degraded by large factors (2x or 5x or
something like that, if I remember your earlier emails). Is that right?

I thought I heard about some memory-defrag patches being posted.  
What happens if these are used together with SLOB? Does one regain the
lost performance? Perhaps maybe one gets even better performance?

--linas

^ permalink raw reply

* [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Scott Wood @ 2007-07-09 19:57 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

In older versions of glibc (through 2.3), the dynamic linker executes a
small amount of code from the data segment, which is not marked as
executable.  A recent change (commit 9ba4ace39fdfe22268daca9f28c5df384ae462cf)
stops this from working; there should be a deprecation period before
older glibc versions stop working.

The problem has been observed on glibc 2.2.  While glibc 2.3 has the same
code, I did not see the problem; it may be that it accesses the page in
question as data before executing from it, and thus it is already mapped.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Unfortunately, this didn't make it into 2.6.22, but it should probably go
into the stable branch...

 arch/powerpc/mm/fault.c |   22 +++++++++++++++++++++-
 1 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0ece513..2445512 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -125,6 +125,18 @@ static void do_dabr(struct pt_regs *regs, unsigned long address,
 }
 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
 
+#ifdef CONFIG_PPC32
+static void warn_exec_from_noexec(void)
+{
+	if (printk_ratelimit())
+		printk(KERN_WARNING "Process %s (%d) attempted to execute from "
+		                    "a non-executable page.\n"
+		       KERN_WARNING "This may stop working in future kernels.  "
+		                    "Please upgrade your libc.\n",
+		       current->comm, current->pid);
+}
+#endif
+
 /*
  * For 600- and 800-family processors, the error_code parameter is DSISR
  * for a data fault, SRR1 for an instruction fault. For 400-family processors
@@ -283,8 +295,16 @@ good_area:
 		/* protection fault */
 		if (error_code & DSISR_PROTFAULT)
 			goto bad_area;
-		if (!(vma->vm_flags & VM_EXEC))
+		if (!(vma->vm_flags & VM_EXEC)) {
+#ifdef CONFIG_PPC32
+			if (vma->vm_flags & VM_READ)
+				warn_exec_from_noexec();
+			else
+				goto bad_area;
+#else
 			goto bad_area;
+#endif
+		}
 #else
 		pte_t *ptep;
 		pmd_t *pmdp;
-- 
1.5.0.3

^ permalink raw reply related

* Re: [PATCH][POWERPC] document ipic level/sense info
From: Kim Phillips @ 2007-07-09 21:08 UTC (permalink / raw)
  To: Stuart Yoder; +Cc: linuxppc-dev, paulus
In-Reply-To: <200707091820.l69IKjBU013685@ld0164-tx32.am.freescale.net>

On Mon, 9 Jul 2007 13:20:45 -0500
Stuart Yoder <b08248@freescale.com> wrote:

> +5) Freescale IPIC Interrupt Controllers
> +---------------------------------------
> +
> +IPIC interrupt controllers are specific to Freescale 83xx
> +SOCs.  Two cells are required to encode interrupt information.
> +The first cell defines the interrupt number.  The second cell
> +defines the sense and level information.
> +
> +Sense and level information follows the Linux convention
> +(specified in include/linux/interrupt.h) and should be encoded
> +as follows:
> +
> +	1 =  low to high edge sensitive type enabled

the IPIC doesn't support this sense type.

> +	2 =  high to low edge sensitive type enabled
> +	4 =  active high level sensitive type enabled

nor this.

i.e, sense types 1 and 4 should not be documented in an IPIC context.

Kim

^ permalink raw reply

* Re: [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Arnd Bergmann @ 2007-07-09 20:25 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070709195743.GA26089@ld0162-tx32.am.freescale.net>

On Monday 09 July 2007, Scott Wood wrote:
> In older versions of glibc (through 2.3), the dynamic linker executes a
> small amount of code from the data segment, which is not marked as
> executable. =A0A recent change (commit 9ba4ace39fdfe22268daca9f28c5df384a=
e462cf)
> stops this from working; there should be a deprecation period before
> older glibc versions stop working.
>=20
> The problem has been observed on glibc 2.2. =A0While glibc 2.3 has the sa=
me
> code, I did not see the problem; it may be that it accesses the page in
> question as data before executing from it, and thus it is already mapped.

I may be missing the obvious, but doesn't that defeat the purpose of
non-executable mappings?

	Arnd <><

^ permalink raw reply

* Re: [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Scott Wood @ 2007-07-09 21:16 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, paulus
In-Reply-To: <200707092225.25287.arnd@arndb.de>

Arnd Bergmann wrote:
> On Monday 09 July 2007, Scott Wood wrote:
> 
>>In older versions of glibc (through 2.3), the dynamic linker executes a
>>small amount of code from the data segment, which is not marked as
>>executable.  A recent change (commit 9ba4ace39fdfe22268daca9f28c5df384ae462cf)
>>stops this from working; there should be a deprecation period before
>>older glibc versions stop working.
>>
>>The problem has been observed on glibc 2.2.  While glibc 2.3 has the same
>>code, I did not see the problem; it may be that it accesses the page in
>>question as data before executing from it, and thus it is already mapped.
> 
> 
> I may be missing the obvious, but doesn't that defeat the purpose of
> non-executable mappings?

The hardware in question doesn't support non-executable mappings; 
otherwise, it'd never have worked in the first place.  Note that this is 
only allowed on 32-bit, non-book-E.

There isn't much value in enforcing non-exec mappings only if it happens 
to be the first fault on a given page.

-Scott

^ permalink raw reply


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