Skip to contentSkip to conversation

ehca: queue page table handling

PATCH In review Heiko J Schick 2 participants 2 messages Apr 27, 2006 InfiniBand

lore
Share & tools
lore
#0 lore raw

PATCH 15/16 ehca: queue page table handling

 ipz_pt_fn.c |  184 ++++++++++++++++++++++++++++++++++++++++++
 ipz_pt_fn.h |  258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 442 insertions(+)
drivers/infiniband/hw/ehca/ipz_pt_fn.h +258 -0
@@ -0,0 +1,258 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  internal queue handling
+ *
+ *  Authors: Waleri Fomin <[email protected]>
+ *           Reinhard Ernst <[email protected]>
+ *           Christoph Raisch <[email protected]>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  $Id: ipz_pt_fn.h,v 1.6 2006/03/26 22:48:21 nguyen Exp $
+ */
+
+#ifndef __IPZ_PT_FN_H__
+#define __IPZ_PT_FN_H__
+
+#include "ehca_qes.h"
+#define EHCA_PAGESHIFT   12
+#define EHCA_PAGESIZE   4096UL
+#define EHCA_PT_ENTRIES 512UL
+
+#include "ehca_tools.h"
+#include "ehca_qes.h"
+
+/* struct generic ehca page
+ */
+struct ipz_page {
+	u8 entries[EHCA_PAGESIZE];
+};
+
+/* struct generic queue in linux kernel virtual memory (kv)
+ */
+struct ipz_queue {
+	u64 current_q_offset;	/* current queue entry */
+
+	struct ipz_page **queue_pages;	/* array of pages belonging to queue */
+	u32 qe_size;		/* queue entry size */
+	u32 act_nr_of_sg;
+	u32 queue_length;	/* queue length allocated in bytes */
+	u32 pagesize;
+	u32 toggle_state;	/* toggle flag - per page */
+	u32 dummy3;		/* 64 bit alignment */
+};
+
+/*  return current Queue Entry for a certain q_offset
+ *   returns address (kv) of Queue Entry
+ */
+static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
+{
+	struct ipz_page *current_page = NULL;
+	if (q_offset >= queue->queue_length) {
+		return NULL;
+	}
+	current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
+	return  &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
+}
+
+/*  return current Queue Entry
+ *   returns address (kv) of Queue Entry
+ */
+static inline void *ipz_qeit_get(struct ipz_queue *queue)
+{
+	return ipz_qeit_calc(queue, queue->current_q_offset);
+}
+
+/*  return current Queue Page , increment Queue Page iterator from
+ *   page to page in struct ipz_queue, last increment will return 0! and
+ *   NOT wrap
+ *   returns address (kv) of Queue Page
+ *   warning don't use in parallel with ipz_QE_get_inc()
+ */
+void *ipz_qpageit_get_inc(struct ipz_queue *queue);
+
+/*  return current Queue Entry, increment Queue Entry iterator by one
+ *   step in struct ipz_queue, will wrap in ringbuffer
+ *   @returns address (kv) of Queue Entry BEFORE increment
+ *   warning don't use in parallel with ipz_qpageit_get_inc()
+ *   warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ */
+static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
+{
+	void *retvalue = NULL;
+
+	retvalue = ipz_qeit_get(queue);
+	queue->current_q_offset += queue->qe_size;
+	if (queue->current_q_offset >= queue->queue_length) {
+		queue->current_q_offset = 0;
+		/* toggle the valid flag */
+		queue->toggle_state = (~queue->toggle_state) & 1;
+	}
+
+	EDEB(7, "queue=%p retvalue=%p new current_q_addr=%lx qe_size=%x",
+	     queue, retvalue, queue->current_q_offset, queue->qe_size);
+
+	return (retvalue);
+}
+
+/*  return current Queue Entry, increment Queue Entry iterator by one
+ *   step in struct ipz_queue, will wrap in ringbuffer
+ *   returns address (kv) of Queue Entry BEFORE increment
+ *   returns 0 and does not increment, if wrong valid state
+ *   warning don't use in parallel with ipz_qpageit_get_inc()
+ *   warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ */
+inline static void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
+{
+	void *retvalue = ipz_qeit_get(queue);
+	u32 qe = ((struct ehca_cqe *)retvalue)->cqe_flags;
+	if ((qe >> 7) == (queue->toggle_state & 1)) {
+		/* this is a good one */
+		ipz_qeit_get_inc(queue);
+	} else
+		retvalue = NULL;
+	return (retvalue);
+}
+
+/*  returns and resets Queue Entry iterator
+ *   returns address (kv) of first Queue Entry
+ */
+static inline void *ipz_qeit_reset(struct ipz_queue *queue)
+{
+	queue->current_q_offset = 0;
+	return (ipz_qeit_get(queue));
+}
+
+/** struct generic page table
+ */
+struct ipz_pt {
+	u64 entries[EHCA_PT_ENTRIES];
+};
+
+/* struct page table for a queue, only to be used in pf
+ */
+struct ipz_qpt {
+	/* queue page tables (kv), use u64 because we know the element length */
+	u64 *qpts;
+	u32 allocated_qpts_entries;
+	u32 nr_of_PTEs;		/*  number of page table entries PTE iterators */
+	u64 *current_pte_addr;
+};
+
+/* constructor for a ipz_queue_t, placement new for ipz_queue_t,
+ *  new for all dependent datastructors
+ *
+ *  all QP Tables are the same
+ *  flow:
+ *     allocate+pin queue
+ *  see ipz_qpt_ctor()
+ *  returns true if ok, false if out of memory
+ */
+int ipz_queue_ctor(struct ipz_queue *queue, const u32 nr_of_pages, const u32 pagesize, const u32 qe_size,	/* queue entry size */
+		   const u32 nr_of_sg);
+
+/* destructor for a ipz_queue_t
+ *  -# free queue
+ *  see ipz_queue_ctor()
+ *  returns true if ok, false if queue was NULL-ptr of free failed
+ */
+int ipz_queue_dtor(struct ipz_queue *queue);
+
+/* constructor for a ipz_qpt_t,
+ * placement new for struct ipz_queue, new for all dependent datastructors
+ *
+ *  all QP Tables are the same,
+ *  flow:
+ *  -# allocate+pin queue
+ *  -# initialise ptcb
+ *  -# allocate+pin PTs
+ *  -# link PTs to a ring, according to HCA Arch, set bit62 id needed
+ *  -# the ring must have room for exactly nr_of_PTEs
+ *  see ipz_qpt_ctor()
+ */
+void ipz_qpt_ctor(struct ipz_qpt *qpt,
+		  const u32 nr_of_QEs,
+		  const u32 pagesize,
+		  const u32 qe_size,
+		  const u8 lowbyte, const u8 toggle,
+		  u32 * act_nr_of_QEs, u32 * act_nr_of_pages);
+
+/*  return current Queue Entry, increment Queue Entry iterator by one
+ *   step in struct ipz_queue, will wrap in ringbuffer
+ *   returns address (kv) of Queue Entry BEFORE increment
+ *   warning don't use in parallel with ipz_qpageit_get_inc()
+ *   warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ *
+ *   fix EQ page problems
+ */
+void *ipz_qeit_eq_get_inc(struct ipz_queue *queue);
+
+/*  return current Event Queue Entry, increment Queue Entry iterator
+ *   by one step in struct ipz_queue if valid, will wrap in ringbuffer
+ *   returns address (kv) of Queue Entry BEFORE increment
+ *   returns 0 and does not increment, if wrong valid state
+ *   warning don't use in parallel with ipz_queue_QPageit_get_inc()
+ *   warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ */
+inline static void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
+{
+	void *retvalue = ipz_qeit_get(queue);
+	u32 qe = *(u8 *) retvalue;
+	EDEB(7, "ipz_QEit_EQ_get_inc_valid qe=%x", qe);
+	if ((qe >> 7) == (queue->toggle_state & 1)) {
+		/* this is a good one */
+		ipz_qeit_eq_get_inc(queue);
+	} else {
+		retvalue = NULL;
+	}
+	return (retvalue);
+}
+
+/*
+ *   returns address (GX) of first queue entry
+ */
+inline static u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
+{
+	return (be64_to_cpu(qpt->qpts[0]));
+}
+
+/*
+ *   returns address (kv) of first page of queue page table
+ */
+inline static void *ipz_qpt_get_qpt(struct ipz_qpt *qpt)
+{
+	return (qpt->qpts);
+}
+
+#endif				/* __IPZ_PT_FN_H__ */
drivers/infiniband/hw/ehca/ipz_pt_fn.c +184 -0

184 lines not on this page · raw message

#1 lore raw

drivers/infiniband/hw/ehca/ipz_pt_fn.h line 146

Quoted 11 lines · Heiko J Schick
drivers/infiniband/hw/ehca/ipz_pt_fn.h +11 -0
+inline static void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
+{
+	void *retvalue = ipz_qeit_get(queue);
+	u32 qe = ((struct ehca_cqe *)retvalue)->cqe_flags;
+	if ((qe >> 7) == (queue->toggle_state & 1)) {
+		/* this is a good one */
+		ipz_qeit_get_inc(queue);
+	} else
+		retvalue = NULL;
+	return (retvalue);
+}

How about:
static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)

{
	struct ehca_cqe *cqe = ipz_qeit_get(queue);
	u32 flags = cqe->cqe_flags;

	if ((flags >> 7) != (queue->toggle_state & 1))
		return NULL;

	ipz_qeit_get_inc(queue);
	return cqe;
}

o "static inline", as Arnd requested,
o no cast for cqe,
o possibly useful identifier for "retvalue",
o trivial to identify error path (hint: only error path is indented),
o directly returns NULL instead of assigning to a variable,
o removed brackets around return value.

I'm still not happy with "ehca_cqe" (just try to pronounce it) and the weird condition. But you should get the general idea. Same goes for other functions.

Jörn

Signature · 3 lines
The cheapest, fastest and most reliable components of a computer
system are those that aren't there.
-- Gordon Bell, DEC labratories