[PATCH 2.6.31] ehea: Fix napi list corruption on ifconfig down

2009-08-04 Thread Hannes Hering
This patch fixes the napi list handling when an ehea interface is shut down to
avoid corruption of the napi list.

Signed-off-by: Hannes Hering heri...@de.ibm.com

---

diff -Nurp -X dontdiff linux-2.6.31-rc5/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.31-rc5/drivers/net/ehea/ehea.h2009-08-01 02:40:45.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2009-08-03 17:59:26.696079433 
+0200
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0101
+#define DRV_VERSIONEHEA_0102
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.31-rc5/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.31-rc5/drivers/net/ehea/ehea_main.c   2009-08-01 
02:40:45.0 +0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2009-08-03 17:59:26.696079433 
+0200
@@ -1545,6 +1545,9 @@ static int ehea_clean_portres(struct ehe
 {
int ret, i;
 
+   if (pr-qp)
+   netif_napi_del(pr-napi);
+
ret = ehea_destroy_qp(pr-qp);
 
if (!ret) {
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages

2009-06-10 Thread Hannes Hering
Hi Michael,

On Wednesday 10 June 2009 02:02:36 Michael Ellerman wrote:
 For those of us who haven't read the HEA spec lately, can you give us
 some more detail on that? :)
first of all, please note that this patch is actually for the ehca infiniband
driver. The ehca driver uses an internal memory region, which is supposed to
contain all physical memory. A memory region maps a virtually contiguous
adapter address space to the physical or better absolute address space. The
limitation is that the memory region cannot map non-contiguous virtual adapter
address space. However, on ppc64 machines there is a feature to dynamically add
or remove memory to logical partitions during runtime. These operations scatter
the absolute memory so that the kernel memory has a non-contiguous layout. This
layout cannot be represented in a memory region. The purpose of this code is to
detect the memory layout so that the memory region can be made up of the
existing memory chunks. It also translates the kernel addresses to the memory
region address, which is needed for interaction with the HCA.
 How does it interact with kexec/kdump?
We never tested the ehca driver with kexec/kdump. This patch also doesn't
improve anything in this context.

 phys_to_abs() ? As below, or does it come from somewhere else?
You're right, actually that isn't needed on System p. On the other hand I
needed to choose an address type, which is the base of all mapping. The
busmap holds all addresses as absolute addresses. The absolute addresses can
then be converted in any other type (virt, phys). 

Regards

Hannes

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages

2009-06-09 Thread Hannes Hering
This patch implements toleration of dynamic memory operations and 16 GB
gigantic pages. On module load the driver walks through available system
memory, checks for available memory ranges and then registers the kernel
internal memory region accordingly. The translation of address ranges is
implemented via a 3-level busmap.

Signed-off-by: Hannes Hering heri...@de.ibm.com

---
This patch is built and tested against infiniband.git. Please apply for 2.6.31.

Regards

Hannes

Index: infiniband/drivers/infiniband/hw/ehca/ehca_main.c
===
--- infiniband.orig/drivers/infiniband/hw/ehca/ehca_main.c  2009-06-09 
14:20:37.0 +0200
+++ infiniband/drivers/infiniband/hw/ehca/ehca_main.c   2009-06-09 
14:20:47.0 +0200
@@ -52,7 +52,7 @@
 #include ehca_tools.h
 #include hcp_if.h
 
-#define HCAD_VERSION 0026
+#define HCAD_VERSION 0027
 
 MODULE_LICENSE(Dual BSD/GPL);
 MODULE_AUTHOR(Christoph Raisch rai...@de.ibm.com);
@@ -506,6 +506,7 @@
shca-ib_device.detach_mcast= ehca_detach_mcast;
shca-ib_device.process_mad = ehca_process_mad;
shca-ib_device.mmap= ehca_mmap;
+   shca-ib_device.dma_ops = ehca_dma_mapping_ops;
 
if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca-hca_cap)) {
shca-ib_device.uverbs_cmd_mask |=
@@ -1028,17 +1029,23 @@
goto module_init1;
}
 
+   ret = ehca_create_busmap();
+   if (ret) {
+   ehca_gen_err(Cannot create busmap.);
+   goto module_init2;
+   }
+
ret = ibmebus_register_driver(ehca_driver);
if (ret) {
ehca_gen_err(Cannot register eHCA device driver);
ret = -EINVAL;
-   goto module_init2;
+   goto module_init3;
}
 
ret = register_memory_notifier(ehca_mem_nb);
if (ret) {
ehca_gen_err(Failed registering memory add/remove notifier);
-   goto module_init3;
+   goto module_init4;
}
 
if (ehca_poll_all_eqs != 1) {
@@ -1053,9 +1060,12 @@
 
return 0;
 
-module_init3:
+module_init4:
ibmebus_unregister_driver(ehca_driver);
 
+module_init3:
+   ehca_destroy_busmap();
+
 module_init2:
ehca_destroy_slab_caches();
 
@@ -1073,6 +1083,8 @@
 
unregister_memory_notifier(ehca_mem_nb);
 
+   ehca_destroy_busmap();
+
ehca_destroy_slab_caches();
 
ehca_destroy_comp_pool();
Index: infiniband/drivers/infiniband/hw/ehca/ehca_mrmw.c
===
--- infiniband.orig/drivers/infiniband/hw/ehca/ehca_mrmw.c  2009-06-09 
14:20:37.0 +0200
+++ infiniband/drivers/infiniband/hw/ehca/ehca_mrmw.c   2009-06-09 
14:20:47.0 +0200
@@ -53,6 +53,39 @@
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
+/* DMEM toleration management */
+#define EHCA_SECTSHIFTSECTION_SIZE_BITS
+#define EHCA_SECTSIZE  (1UL  EHCA_SECTSHIFT)
+#define EHCA_HUGEPAGESHIFT 34
+#define EHCA_HUGEPAGE_SIZE (1UL  EHCA_HUGEPAGESHIFT)
+#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1)  PAGE_SHIFT)
+#define EHCA_INVAL_ADDR0xULL
+#define EHCA_DIR_INDEX_SHIFT 13   /* 8k Entries in 64k block */
+#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2)
+#define EHCA_MAP_ENTRIES (1  EHCA_DIR_INDEX_SHIFT)
+#define EHCA_TOP_MAP_SIZE (0x1)   /* currently fixed map size 
*/
+#define EHCA_DIR_MAP_SIZE (0x1)
+#define EHCA_ENT_MAP_SIZE (0x1)
+#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1)
+#define EHCA_REG_MR 0
+#define EHCA_REG_BUSMAP_MR (~0)
+
+static unsigned long ehca_mr_len;
+/*
+ * Memory map data structures
+ */
+struct ehca_dir_bmap {
+   u64 ent[EHCA_MAP_ENTRIES];
+};
+struct ehca_top_bmap {
+   struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES];
+};
+struct ehca_bmap {
+   struct ehca_top_bmap *top[EHCA_MAP_ENTRIES];
+};
+
+static struct ehca_bmap *ehca_bmap;
+
 static struct kmem_cache *mr_cache;
 static struct kmem_cache *mw_cache;
 
@@ -68,6 +101,8 @@
 #define EHCA_MR_PGSHIFT1M  20
 #define EHCA_MR_PGSHIFT16M 24
 
+static u64 ehca_map_vaddr(void *caddr);
+
 static u32 ehca_encode_hwpage_size(u32 pgsize)
 {
int log = ilog2(pgsize);
@@ -135,7 +170,8 @@
goto get_dma_mr_exit0;
}
 
-   ret = ehca_reg_maxmr(shca, e_maxmr, (u64 *)KERNELBASE,
+   ret = ehca_reg_maxmr(shca, e_maxmr,
+(void *)ehca_map_vaddr((void *)KERNELBASE),
 mr_access_flags, e_pd,
 e_maxmr-ib.ib_mr.lkey,
 e_maxmr-ib.ib_mr.rkey);
@@ -251,7 +287,7 @@
 
ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
  e_pd

Re: [PATCH 2.6.30-rc5] ehea: fix invalid pointer access

2009-05-05 Thread Hannes Hering
On Tuesday 05 May 2009 11:11:27 David Howells wrote:
 Hannes Hering hannes.her...@linux.vnet.ibm.com wrote:
 
  pref = skb_array[x];
  -   prefetchw(pref);
  -   prefetchw(pref + EHEA_CACHE_LINE);
  +   if (pref) {
  +   prefetchw(pref);
  +   prefetchw(pref + EHEA_CACHE_LINE);
 
 Ummm...  Is prefetch() or prefetchw() faulting?
 
 David
Hi David,

this is an ehea driver problem, which is occuring when the receive queue runs
empty. The faulting code is more specifically the following line:

pref = (skb_array[x]-data);

Here the access to the struct element data would cause an exception.We could
have made the if block a little smaller.

Regards

Hannes
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2.6.30-rc5] ehea: fix invalid pointer access

2009-05-05 Thread Hannes Hering
On Tuesday 05 May 2009 14:19:54 David Howells wrote:
 In that case, you might want to move the prefetchw() calls in the following:
 
   pref = skb_array[x];
   -   prefetchw(pref);
   -   prefetchw(pref + EHEA_CACHE_LINE);
   +   if (pref) {
   +   prefetchw(pref);
   +   prefetchw(pref + EHEA_CACHE_LINE);
 
 to before the if-statement.  That way the CPU can be attempting the prefetch
 whilst it's chewing over the test and branch.  prefetching shouldn't fault on
 a bad address.
 
 David
Hi David,

you are right so far, but actually the prefetch calls on POWER also contain
an if statement to check if the address is valid (i. e. non-zero). We never
have the case that the pref != NULL and pref-data == NULL. And the situation
of pref==NULL is very rare. This means there is no benefit moving our if
statement down from performance perspective if we assume that our if does not
take longer then the if in the prefetch command. We can add an
if(likely(pref) if you like. In fact doing the if statement as we do it now
we actually save the prefetch if statements in case we hit the situation of
pref==NULL.

Regards

Hannes
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ehea: Fix some whitespace issues

2008-11-05 Thread Hannes Hering
This patch removes some trailing whitespaces and spaces before tabs.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---
diff -Nurp -X dontdiff linux-2.6.28-rc3/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.28-rc3/drivers/net/ehea/ehea.h2008-11-02 23:17:19.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-11-05 10:10:14.563107976 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0095
+#define DRV_VERSIONEHEA_0096
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.28-rc3/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-2.6.28-rc3/drivers/net/ehea/ehea_qmr.c2008-11-02 
23:17:19.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-11-05 10:10:14.563107976 
+0100
@@ -653,7 +653,7 @@ static int ehea_update_busmap(unsigned l
int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
int idx = i  EHEA_INDEX_MASK;
-   
+
if (add) {
int ret = ehea_init_bmap(ehea_bmap, top, dir);
if (ret)
@@ -780,7 +780,7 @@ void ehea_destroy_busmap(void)
 
kfree(ehea_bmap);
ehea_bmap = NULL;
-out_destroy:   
+out_destroy:
mutex_unlock(ehea_busmap_mutex);
 }
 
@@ -858,10 +858,10 @@ static u64 ehea_reg_mr_sections(int top,
for (idx = 0; idx  EHEA_MAP_ENTRIES; idx++) {
if (!ehea_bmap-top[top]-dir[dir]-ent[idx])
continue;
-   
+
hret = ehea_reg_mr_section(top, dir, idx, pt, adapter, mr);
if ((hret != H_SUCCESS)  (hret != H_PAGE_REGISTERED))
-   return hret;
+   return hret;
}
return hret;
 }
@@ -879,7 +879,7 @@ static u64 ehea_reg_mr_dir_sections(int 
 
hret = ehea_reg_mr_sections(top, dir, pt, adapter, mr);
if ((hret != H_SUCCESS)  (hret != H_PAGE_REGISTERED))
-   return hret;
+   return hret;
}
return hret;
 }
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ehea: Fix memory hotplug support

2008-10-16 Thread Hannes Hering
This patch implements the memory notifier to update the busmap instantly
instead of rebuilding the whole map. This is necessary because
walk_memory_resource provides different information than required during memory
hotplug.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---
Jeff, as requested, this patch is now based on davem's net-2.6.git.

diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.27/drivers/net/ehea/ehea.h2008-10-16 11:22:15.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-10-16 11:23:00.646563117 
+0200
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0093
+#define DRV_VERSIONEHEA_0094
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.27/drivers/net/ehea/ehea_main.c   2008-10-16 11:22:15.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-10-16 11:23:00.646563117 
+0200
@@ -2863,7 +2863,7 @@ static void ehea_rereg_mrs(struct work_s
struct ehea_adapter *adapter;
 
mutex_lock(dlpar_mem_lock);
-   ehea_info(LPAR memory enlarged - re-initializing driver);
+   ehea_info(LPAR memory changed - re-initializing driver);
 
list_for_each_entry(adapter, adapter_list, list)
if (adapter-active_ports) {
@@ -2900,13 +2900,6 @@ static void ehea_rereg_mrs(struct work_s
}
}
 
-   ehea_destroy_busmap();
-   ret = ehea_create_busmap();
-   if (ret) {
-   ehea_error(creating ehea busmap failed);
-   goto out;
-   }
-
clear_bit(__EHEA_STOP_XFER, ehea_driver_flags);
 
list_for_each_entry(adapter, adapter_list, list)
@@ -3519,9 +3512,21 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   struct memory_notify *arg = data;
switch (action) {
-   case MEM_OFFLINE:
-   ehea_info(memory has been removed);
+   case MEM_CANCEL_OFFLINE:
+   ehea_info(memory offlining canceled);
+   /* Readd canceled memory block */
+   case MEM_ONLINE:
+   ehea_info(memory is going online);
+   if (ehea_add_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
+   ehea_rereg_mrs(NULL);
+   break;
+   case MEM_GOING_OFFLINE:
+   ehea_info(memory is going offline);
+   if (ehea_rem_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
ehea_rereg_mrs(NULL);
break;
default:
diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-2.6.27/drivers/net/ehea/ehea_qmr.c2008-10-16 11:22:15.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-10-16 11:23:00.646563117 
+0200
@@ -567,7 +567,7 @@ static inline int ehea_calc_index(unsign
 static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap,
 int dir)
 {
-   if(!ehea_top_bmap-dir[dir]) {
+   if (!ehea_top_bmap-dir[dir]) {
ehea_top_bmap-dir[dir] =
kzalloc(sizeof(struct ehea_dir_bmap), GFP_KERNEL);
if (!ehea_top_bmap-dir[dir])
@@ -578,7 +578,7 @@ static inline int ehea_init_top_bmap(str
 
 static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir)
 {
-   if(!ehea_bmap-top[top]) {
+   if (!ehea_bmap-top[top]) {
ehea_bmap-top[top] =
kzalloc(sizeof(struct ehea_top_bmap), GFP_KERNEL);
if (!ehea_bmap-top[top])
@@ -587,53 +587,124 @@ static inline int ehea_init_bmap(struct 
return ehea_init_top_bmap(ehea_bmap-top[top], dir);
 }
 
-static int ehea_create_busmap_callback(unsigned long pfn,
-  unsigned long nr_pages, void *arg)
-{
-   unsigned long i, mr_len, start_section, end_section;
-   start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
-   end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
-   mr_len = *(unsigned long *)arg;
+static DEFINE_MUTEX(ehea_busmap_mutex);
+static unsigned long ehea_mr_len;
 
-   if (!ehea_bmap)
-   ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
-   if (!ehea_bmap)
-   return -ENOMEM;
+#define EHEA_BUSMAP_ADD_SECT 1
+#define EHEA_BUSMAP_REM_SECT 0
 
-   for (i = start_section; i  end_section; i++) {
-   int ret;
-   int top, dir, idx;
-   u64 vaddr;
+static void ehea_rebuild_busmap(void)
+{
+   u64 vaddr = EHEA_BUSMAP_START;
+   int top, dir, idx;
+
+   for (top

[PATCH] ehea: Fix memory hotplug support

2008-10-15 Thread Hannes Hering
This patch implements the memory notifier to update the busmap instantly
instead of rebuilding the whole map. This is necessary because
walk_memory_resource provides different information than required during memory
hotplug.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---
This patch is based on the current netdev-2.6-git. It supersedes the previous
post ehea: Fix memory hotplug support.
http://www.spinics.net/lists/netdev/msg75413.html

diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.27/drivers/net/ehea/ehea.h2008-10-14 18:26:54.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-10-15 11:47:23.0 
+0200
@@ -40,13 +40,13 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0092
+#define DRV_VERSIONEHEA_0094
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
 #define DLPAR_MEM_ADD  2
 #define DLPAR_MEM_REM  4
-#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD)
+#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.27/drivers/net/ehea/ehea_main.c   2008-10-14 18:26:54.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-10-15 11:47:23.0 
+0200
@@ -2863,7 +2863,7 @@ static void ehea_rereg_mrs(struct work_s
struct ehea_adapter *adapter;
 
mutex_lock(dlpar_mem_lock);
-   ehea_info(LPAR memory enlarged - re-initializing driver);
+   ehea_info(LPAR memory changed - re-initializing driver);
 
list_for_each_entry(adapter, adapter_list, list)
if (adapter-active_ports) {
@@ -2900,13 +2900,6 @@ static void ehea_rereg_mrs(struct work_s
}
}
 
-   ehea_destroy_busmap();
-   ret = ehea_create_busmap();
-   if (ret) {
-   ehea_error(creating ehea busmap failed);
-   goto out;
-   }
-
clear_bit(__EHEA_STOP_XFER, ehea_driver_flags);
 
list_for_each_entry(adapter, adapter_list, list)
@@ -3519,9 +3512,21 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   struct memory_notify *arg = data;
switch (action) {
-   case MEM_OFFLINE:
-   ehea_info(memory has been removed);
+   case MEM_CANCEL_OFFLINE:
+   ehea_info(memory offlining canceled);
+   /* Readd canceled memory block */
+   case MEM_ONLINE:
+   ehea_info(memory is going online);
+   if (ehea_add_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
+   ehea_rereg_mrs(NULL);
+   break;
+   case MEM_GOING_OFFLINE:
+   ehea_info(memory is going offline);
+   if (ehea_rem_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
ehea_rereg_mrs(NULL);
break;
default:
diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-2.6.27/drivers/net/ehea/ehea_qmr.c2008-10-14 18:26:54.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-10-15 11:47:23.0 
+0200
@@ -567,7 +567,7 @@ static inline int ehea_calc_index(unsign
 static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap,
 int dir)
 {
-   if(!ehea_top_bmap-dir[dir]) {
+   if (!ehea_top_bmap-dir[dir]) {
ehea_top_bmap-dir[dir] =
kzalloc(sizeof(struct ehea_dir_bmap), GFP_KERNEL);
if (!ehea_top_bmap-dir[dir])
@@ -578,7 +578,7 @@ static inline int ehea_init_top_bmap(str
 
 static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir)
 {
-   if(!ehea_bmap-top[top]) {
+   if (!ehea_bmap-top[top]) {
ehea_bmap-top[top] =
kzalloc(sizeof(struct ehea_top_bmap), GFP_KERNEL);
if (!ehea_bmap-top[top])
@@ -587,52 +587,124 @@ static inline int ehea_init_bmap(struct 
return ehea_init_top_bmap(ehea_bmap-top[top], dir);
 }
 
-static int ehea_create_busmap_callback(unsigned long pfn,
-  unsigned long nr_pages, void *arg)
-{
-   unsigned long i, mr_len, start_section, end_section;
-   start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
-   end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
-   mr_len = *(unsigned long *)arg;
+static DEFINE_MUTEX(ehea_busmap_mutex);
+static unsigned long ehea_mr_len;
 
-   ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL

[PATCH] [2.6.27] ehea: Fix memory hotplug support

2008-09-17 Thread Hannes Hering
This patch implements the memory notifier to update the busmap instantly
instead of rebuilding the whole map. This is necessary because
walk_memory_resource provides different information than required during memory
hotplug.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---
This patch is based on upstream-fixes in the netdev-2.6.git.

diff -Nurp -X dontdiff linux-netdev-2.6/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-netdev-2.6/drivers/net/ehea/ehea.h2008-09-17 16:09:25.729017931 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-09-17 16:11:26.481026217 
+0200
@@ -40,13 +40,13 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0092
+#define DRV_VERSIONEHEA_0094
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
 #define DLPAR_MEM_ADD  2
 #define DLPAR_MEM_REM  4
-#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD)
+#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff -Nurp -X dontdiff linux-netdev-2.6/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-netdev-2.6/drivers/net/ehea/ehea_main.c   2008-09-17 
16:09:25.729017931 +0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-09-17 16:11:26.481026217 
+0200
@@ -2863,7 +2863,7 @@ static void ehea_rereg_mrs(struct work_s
struct ehea_adapter *adapter;
 
mutex_lock(dlpar_mem_lock);
-   ehea_info(LPAR memory enlarged - re-initializing driver);
+   ehea_info(LPAR memory changed - re-initializing driver);
 
list_for_each_entry(adapter, adapter_list, list)
if (adapter-active_ports) {
@@ -2900,13 +2900,6 @@ static void ehea_rereg_mrs(struct work_s
}
}
 
-   ehea_destroy_busmap();
-   ret = ehea_create_busmap();
-   if (ret) {
-   ehea_error(creating ehea busmap failed);
-   goto out;
-   }
-
clear_bit(__EHEA_STOP_XFER, ehea_driver_flags);
 
list_for_each_entry(adapter, adapter_list, list)
@@ -3519,9 +3512,20 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   struct memory_notify *arg = data;
switch (action) {
-   case MEM_OFFLINE:
-   ehea_info(memory has been removed);
+   case MEM_CANCEL_OFFLINE:
+   ehea_info(memory offlining canceled);
+   case MEM_ONLINE:
+   ehea_info(memory is going online);
+   if (ehea_add_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
+   ehea_rereg_mrs(NULL);
+   break;
+   case MEM_GOING_OFFLINE:
+   ehea_info(memory is going offline);
+   if (ehea_rem_sect_bmap(arg-start_pfn, arg-nr_pages))
+   return NOTIFY_BAD;
ehea_rereg_mrs(NULL);
break;
default:
diff -Nurp -X dontdiff linux-netdev-2.6/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-netdev-2.6/drivers/net/ehea/ehea_qmr.c2008-09-17 
16:09:25.729017931 +0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-09-17 16:11:26.481026217 
+0200
@@ -587,53 +587,81 @@ static inline int ehea_init_bmap(struct 
return ehea_init_top_bmap(ehea_bmap-top[top], dir);
 }
 
-static int ehea_create_busmap_callback(unsigned long pfn,
-  unsigned long nr_pages, void *arg)
+static DEFINE_MUTEX(ehea_busmap_mutex);
+static unsigned long ehea_mr_len;
+
+#define EHEA_BUSMAP_ADD_SECT 1
+#define EHEA_BUSMAP_REM_SECT 0
+
+static int ehea_update_busmap(unsigned long pfn, unsigned long pgnum, int add)
 {
-   unsigned long i, mr_len, start_section, end_section;
-   start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
-   end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
-   mr_len = *(unsigned long *)arg;
+   unsigned long i, start_section, end_section;
 
if (!ehea_bmap)
ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
if (!ehea_bmap)
return -ENOMEM;
 
+   start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
+   end_section = start_section + ((pgnum * PAGE_SIZE) / EHEA_SECTSIZE);
+
for (i = start_section; i  end_section; i++) {
-   int ret;
-   int top, dir, idx;
u64 vaddr;
+   int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
+   int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
+   int idx = i  EHEA_INDEX_MASK;
+
+   int ret = ehea_init_bmap(ehea_bmap, top, dir);
+   if (ret) {
+   if(add) {
+   return ret

Re: + ehea-fix-dlpar-memory-handling.patch added to -mm tree

2008-09-09 Thread Hannes Hering
Hello,

please consider the ehea-fix-dlpar-memory-handling.patch as critical bug fix,
as it fixes a potential firmware error causing the driver to get inoperable
when system memory is sparse. Therefore please include this fix into 2.6.27.

Regards

Hannes

On Tuesday 09 September 2008 00:25:56 you wrote:
 
 The patch titled
  ehea: fix DLPAR memory handling
 has been added to the -mm tree.  Its filename is
  ehea-fix-dlpar-memory-handling.patch
 
 Before you just go and hit reply, please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
   reply-to-all to that, adding suitable additional cc's
 
 *** Remember to use Documentation/SubmitChecklist when testing your code ***
 
 See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
 out what to do about this
 
 The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/
 
 --
 Subject: ehea: fix DLPAR memory handling
 From: Hannes Hering [EMAIL PROTECTED]
 
 The ehea busmap must be allocated only once in the first of many calls of the
 ehea_create_busmap_callback.
 
 Signed-off-by: Hannes Hering [EMAIL PROTECTED]
 Signed-off-by: Andrew Morton [EMAIL PROTECTED]
 ---
 
  drivers/net/ehea/ehea_qmr.c |3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff -puN drivers/net/ehea/ehea_qmr.c~ehea-fix-dlpar-memory-handling 
 drivers/net/ehea/ehea_qmr.c
 --- a/drivers/net/ehea/ehea_qmr.c~ehea-fix-dlpar-memory-handling
 +++ a/drivers/net/ehea/ehea_qmr.c
 @@ -595,7 +595,8 @@ static int ehea_create_busmap_callback(u
   end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
   mr_len = *(unsigned long *)arg;
  
 - ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
 + if (!ehea_bmap)
 + ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
   if (!ehea_bmap)
   return -ENOMEM;
  
 _
 
 Patches currently in -mm which might be from [EMAIL PROTECTED] are
 
 ehea-fix-dlpar-memory-handling.patch
 ehea-enable-dlpar-memory-remove.patch

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/2] ehea: Fix DLPAR memory handling

2008-09-05 Thread Hannes Hering
The ehea busmap must be allocated only once in the first of many calls of the
ehea_create_busmap_callback.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---

diff -Nurp -X dontdiff linux-2.6.27-rc5/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-2.6.27-rc5/drivers/net/ehea/ehea_qmr.c2008-08-29 
00:52:02.0 +0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-09-05 15:31:30.0 
+0200
@@ -595,7 +595,8 @@ static int ehea_create_busmap_callback(u
end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
mr_len = *(unsigned long *)arg;
 
-   ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
+   if (!ehea_bmap)
+   ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
if (!ehea_bmap)
return -ENOMEM;
 
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/2] ehea: Enable DLPAR memory remove

2008-09-05 Thread Hannes Hering
This patch adds the capability flag to the capability list for dynamic LPAR
memory remove to enable this feature.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---

diff -Nurp -X dontdiff linux-2.6.27-rc5/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.27-rc5/drivers/net/ehea/ehea.h2008-08-29 00:52:02.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-09-05 15:33:12.0 
+0200
@@ -40,13 +40,13 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0092
+#define DRV_VERSIONEHEA_0093
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
 #define DLPAR_MEM_ADD  2
 #define DLPAR_MEM_REM  4
-#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD)
+#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2/3] [2.6.26] ehea: Add dependency to Kconfig

2008-06-03 Thread Hannes Hering
Hi Nathan,

I agree that the ehea cannot be built without MEMORY_HOTPLUG. The problem is
the fact that the ppc walk_memory_resource declaration is in the scope of
MEMORY_HOTPLUG. At the moment I don't have complete overview if the move of the
code as you propose in your patch has any side effects. We probably need to
talk to Badari who provided the walk_memory_resource code. We can also just
throw it onto one of our boxes to see what happens. ;)

Regards

Hannes

On Wednesday 28 May 2008 18:44:05 Nathan Lynch wrote:
 Hello,
 
 Hannes Hering wrote:
  The new ehea memory hot plug implementation depends on MEMORY_HOTPLUG.
  
  Signed-off-by: Hannes Hering [EMAIL PROTECTED]
  ---
  
  diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
  index f90a86b..181cd86 100644
  --- a/drivers/net/Kconfig
  +++ b/drivers/net/Kconfig
  @@ -2440,7 +2440,7 @@ config CHELSIO_T3
   
   config EHEA
  tristate eHEA Ethernet support
  -   depends on IBMEBUS  INET  SPARSEMEM
  +   depends on IBMEBUS  INET  SPARSEMEM  MEMORY_HOTPLUG
  select INET_LRO
  ---help---
This driver supports the IBM pSeries eHEA ethernet adapter.
 
 I disagree with this change.
 
 It makes it impossible to build the ehea driver without memory hotplug
 enabled.  Presumably, this commit was intended to work around a build
 break of this sort (with EHEA=m and MEMORY_HOTPLUG=n):
 
 drivers/net/ehea/ehea_qmr.c: In function 'ehea_create_busmap':
 drivers/net/ehea/ehea_qmr.c:635: error: implicit declaration of function 
 'walk_memory_resource'
 
 (some indication of this should have been in the commit message, btw)
 
 I think this was the wrong way to fix the issue.  EHEA=m and
 MEMORY_HOTPLUG=n is a valid configuration for machines I test.
 
 Any thoughts on the following, which makes walk_memory_resource()
 available regardless of MEMORY_HOTPLUG's setting?  I've tested it on a
 JS22 (Power6 blade).
 
 ---
 
  arch/powerpc/mm/mem.c  |3 +--
  drivers/net/Kconfig|2 +-
  include/linux/memory_hotplug.h |   16 
  3 files changed, 10 insertions(+), 11 deletions(-)
 
 diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
 index f67e118..51f82d8 100644
 --- a/arch/powerpc/mm/mem.c
 +++ b/arch/powerpc/mm/mem.c
 @@ -151,6 +151,7 @@ out:
   return ret;
  }
  #endif /* CONFIG_MEMORY_HOTREMOVE */
 +#endif /* CONFIG_MEMORY_HOTPLUG */
 
  /*
   * walk_memory_resource() needs to make sure there is no holes in a given
 @@ -184,8 +185,6 @@ walk_memory_resource(unsigned long start_pfn, unsigned 
 long nr_pages, void *arg,
  }
  EXPORT_SYMBOL_GPL(walk_memory_resource);
 
 -#endif /* CONFIG_MEMORY_HOTPLUG */
 -
  void show_mem(void)
  {
   unsigned long total = 0, reserved = 0;
 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
 index dd0ec9e..f4182cf 100644
 --- a/drivers/net/Kconfig
 +++ b/drivers/net/Kconfig
 @@ -2426,7 +2426,7 @@ config CHELSIO_T3
 
  config EHEA
   tristate eHEA Ethernet support
 - depends on IBMEBUS  INET  SPARSEMEM  MEMORY_HOTPLUG
 + depends on IBMEBUS  INET  SPARSEMEM
   select INET_LRO
   ---help---
 This driver supports the IBM pSeries eHEA ethernet adapter.
 diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
 index 73e3586..ea9f5ad 100644
 --- a/include/linux/memory_hotplug.h
 +++ b/include/linux/memory_hotplug.h
 @@ -77,14 +77,6 @@ extern int __add_pages(struct zone *zone, unsigned long 
 start_pfn,
  extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
   unsigned long nr_pages);
 
 -/*
 - * Walk through all memory which is registered as resource.
 - * arg is (start_pfn, nr_pages, private_arg_pointer)
 - */
 -extern int walk_memory_resource(unsigned long start_pfn,
 - unsigned long nr_pages, void *arg,
 - int (*func)(unsigned long, unsigned long, void *));
 -
  #ifdef CONFIG_NUMA
  extern int memory_add_physaddr_to_nid(u64 start);
  #else
 @@ -199,6 +191,14 @@ static inline void 
 register_page_bootmem_info_node(struct pglist_data *pgdat)
 
  #endif /* ! CONFIG_MEMORY_HOTPLUG */
 
 +/*
 + * Walk through all memory which is registered as resource.
 + * arg is (start_pfn, nr_pages, private_arg_pointer)
 + */
 +extern int walk_memory_resource(unsigned long start_pfn,
 + unsigned long nr_pages, void *arg,
 + int (*func)(unsigned long, unsigned long, void *));
 +
  extern int add_memory(int nid, u64 start, u64 size);
  extern int arch_add_memory(int nid, u64 start, u64 size);
  extern int remove_memory(u64 start, u64 size);
 


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/3] [2.6.26] ehea: Add DLPAR memory remove support

2008-05-07 Thread Hannes Hering
Hi,

this patchset adds memory remove hotplug support for the ehea driver. 

These patches apply against kernel 2.6.26-rc1.

Regards

Hannes
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/3] [2.6.26] memory: Introduce exports for memory notifiers

2008-05-07 Thread Hannes Hering
This patch introduces two exports to allow modules to use memory notifiers.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---

diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 8ce6de5..937e825 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -53,11 +53,13 @@ int register_memory_notifier(struct notifier_block *nb)
 {
 return blocking_notifier_chain_register(memory_chain, nb);
 }
+EXPORT_SYMBOL(register_memory_notifier);
 
 void unregister_memory_notifier(struct notifier_block *nb)
 {
 blocking_notifier_chain_unregister(memory_chain, nb);
 }
+EXPORT_SYMBOL(unregister_memory_notifier);
 
 /*
  * register_memory - Setup a sysfs device for a memory block
-- 
1.5.5.1
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/3] [2.6.26] ehea: Add dependency to Kconfig

2008-05-07 Thread Hannes Hering
The new ehea memory hot plug implementation depends on MEMORY_HOTPLUG.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f90a86b..181cd86 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2440,7 +2440,7 @@ config CHELSIO_T3
 
 config EHEA
tristate eHEA Ethernet support
-   depends on IBMEBUS  INET  SPARSEMEM
+   depends on IBMEBUS  INET  SPARSEMEM  MEMORY_HOTPLUG
select INET_LRO
---help---
  This driver supports the IBM pSeries eHEA ethernet adapter.
-- 
1.5.5.1
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 3/3] [2.6.26] ehea: Add DLPAR memory remove support

2008-05-07 Thread Hannes Hering
The eHEA driver uses the recently modified walk_memory_resource for powerpc
functionality to detect the memory layout. It further uses the memory hotplug
notifiers to catch memory hotplug events.

Signed-off-by: Hannes Hering [EMAIL PROTECTED]
---

diff -Nurp -X dontdiff linux-2.6.26-rc1/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.26-rc1/drivers/net/ehea/ehea.h2008-05-03 20:59:44.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-05-07 14:09:50.0 
+0200
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0090
+#define DRV_VERSIONEHEA_0091
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -118,6 +118,13 @@
 #define EHEA_MR_ACC_CTRL   0x0080
 
 #define EHEA_BUSMAP_START  0x8000ULL
+#define EHEA_INVAL_ADDR0xULL
+#define EHEA_DIR_INDEX_SHIFT 13   /* 8k Entries in 64k block */
+#define EHEA_TOP_INDEX_SHIFT (EHEA_DIR_INDEX_SHIFT * 2)
+#define EHEA_MAP_ENTRIES (1  EHEA_DIR_INDEX_SHIFT)
+#define EHEA_MAP_SIZE (0x1)   /* currently fixed map size 
*/
+#define EHEA_INDEX_MASK (EHEA_MAP_ENTRIES - 1)
+
 
 #define EHEA_WATCH_DOG_TIMEOUT 10*HZ
 
@@ -192,10 +199,20 @@ struct h_epas {
   set to 0 if unused */
 };
 
-struct ehea_busmap {
-   unsigned int entries;   /* total number of entries */
-   unsigned int valid_sections;/* number of valid sections */
-   u64 *vaddr;
+/*
+ * Memory map data structures
+ */
+struct ehea_dir_bmap
+{
+   u64 ent[EHEA_MAP_ENTRIES];
+};
+struct ehea_top_bmap
+{
+   struct ehea_dir_bmap *dir[EHEA_MAP_ENTRIES];
+};
+struct ehea_bmap
+{
+   struct ehea_top_bmap *top[EHEA_MAP_ENTRIES];
 };
 
 struct ehea_qp;
diff -Nurp -X dontdiff linux-2.6.26-rc1/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.26-rc1/drivers/net/ehea/ehea_main.c   2008-05-03 
20:59:44.0 +0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-05-07 14:09:50.0 
+0200
@@ -35,6 +35,7 @@
 #include linux/if_ether.h
 #include linux/notifier.h
 #include linux/reboot.h
+#include linux/memory.h
 #include asm/kexec.h
 #include linux/mutex.h
 
@@ -3503,6 +3504,24 @@ void ehea_crash_handler(void)
  0, H_DEREG_BCMC);
 }
 
+static int ehea_mem_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+   switch (action) {
+   case MEM_OFFLINE:
+   ehea_info(memory has been removed);
+   ehea_rereg_mrs(NULL);
+   break;
+   default:
+   break;
+   }
+   return NOTIFY_OK;
+}
+
+static struct notifier_block ehea_mem_nb = {
+   .notifier_call = ehea_mem_notifier,
+};
+
 static int ehea_reboot_notifier(struct notifier_block *nb,
unsigned long action, void *unused)
 {
@@ -3581,6 +3600,10 @@ int __init ehea_module_init(void)
if (ret)
ehea_info(failed registering reboot notifier);
 
+   ret = register_memory_notifier(ehea_mem_nb);
+   if (ret)
+   ehea_info(failed registering memory remove notifier);
+
ret = crash_shutdown_register(ehea_crash_handler);
if (ret)
ehea_info(failed registering crash handler);
@@ -3604,6 +3627,7 @@ int __init ehea_module_init(void)
 out3:
ibmebus_unregister_driver(ehea_driver);
 out2:
+   unregister_memory_notifier(ehea_mem_nb);
unregister_reboot_notifier(ehea_reboot_nb);
crash_shutdown_unregister(ehea_crash_handler);
 out:
@@ -3621,6 +3645,7 @@ static void __exit ehea_module_exit(void
ret = crash_shutdown_unregister(ehea_crash_handler);
if (ret)
ehea_info(failed unregistering crash handler);
+   unregister_memory_notifier(ehea_mem_nb);
kfree(ehea_fw_handles.arr);
kfree(ehea_bcmc_regs.arr);
ehea_destroy_busmap();
diff -Nurp -X dontdiff linux-2.6.26-rc1/drivers/net/ehea/ehea_qmr.c 
patched_kernel/drivers/net/ehea/ehea_qmr.c
--- linux-2.6.26-rc1/drivers/net/ehea/ehea_qmr.c2008-05-03 
20:59:44.0 +0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-05-07 14:09:50.0 
+0200
@@ -31,8 +31,8 @@
 #include ehea_phyp.h
 #include ehea_qmr.h
 
+struct ehea_bmap *ehea_bmap = NULL;
 
-struct ehea_busmap ehea_bmap = { 0, 0, NULL };
 
 
 static void *hw_qpageit_get_inc(struct hw_queue *queue)
@@ -559,125 +559,253 @@ int ehea_destroy_qp(struct ehea_qp *qp)
return 0;
 }
 
-int ehea_create_busmap(void)
+static inline int ehea_calc_index(unsigned long i, unsigned long s)
 {
-   u64 vaddr = EHEA_BUSMAP_START;
-   unsigned long high_section_index = 0;
-   int i;
+   return (i  s)  EHEA_INDEX_MASK;
+}
 
-   /*
-* Sections are not in ascending order - Loop over all sections and
-* find