]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/ehea.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / ehea.patch
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/ehea.patch b/src/patches/suse-2.6.27.31/patches.drivers/ehea.patch
deleted file mode 100644 (file)
index 2b0e92a..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-Subject: [PATCH] ehea: Fix memory hotplug support                                                                                                                      
-Subject         [PATCH] ehea: Add hugepage detection
-From: Hannes Hering <hannes.hering@linux.vnet.ibm.com>
-References: 436447 - LTC 48713
-References: 439599 - LTC 48958
-References: 477972 - LTC 51731
-
-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.
-
-...
-
-All kernel memory which is used for kernel/hardware data transfer must be registered
-with firmware using "memory regions". 16GB hugepages may not be part of a memory region
-due to firmware restrictions.
-This patch modifies the walk_memory_resource callback fn to filter hugepages and add
-only standard memory to the busmap which is later on used for MR registration.
-
-...
-
-Added missing set_bit() to disable data transfer when a memchange notification is handled
-
-...
-
-Signed-off-by: Thomas Klein <tklein@de.ibm.com>
-Signed-off-by: Hannes Hering <hering2@de.ibm.com>
-Signed-off-by: Olaf Hering <olh@suse.de>
----
- drivers/net/ehea/ehea.h      |    4 
- drivers/net/ehea/ehea_main.c |   27 ++++--
- drivers/net/ehea/ehea_phyp.c |    2 
- drivers/net/ehea/ehea_qmr.c  |  175 ++++++++++++++++++++++++++++++++++++-------
- drivers/net/ehea/ehea_qmr.h  |    5 +
- 5 files changed, 172 insertions(+), 41 deletions(-)
-
---- a/drivers/net/ehea/ehea.h
-+++ b/drivers/net/ehea/ehea.h
-@@ -40,13 +40,13 @@
- #include <asm/io.h>
- #define DRV_NAME      "ehea"
--#define DRV_VERSION   "EHEA_0092"
-+#define DRV_VERSION   "EHEA_0094-02"
- /* 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)
---- a/drivers/net/ehea/ehea_main.c
-+++ b/drivers/net/ehea/ehea_main.c
-@@ -2869,7 +2869,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) {
-@@ -2906,13 +2906,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)
-@@ -3525,9 +3518,23 @@ 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");
-+              set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
-+              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");
-+              set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
-+              if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
-+                      return NOTIFY_BAD;
-               ehea_rereg_mrs(NULL);
-               break;
-       default:
---- a/drivers/net/ehea/ehea_phyp.c
-+++ b/drivers/net/ehea/ehea_phyp.c
-@@ -535,7 +535,7 @@ u64 ehea_h_query_ehea(const u64 adapter_
-                                      cb_logaddr,              /* R5 */
-                                      0, 0, 0, 0, 0);          /* R6-R10 */
- #ifdef DEBUG
--      ehea_dmp(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
-+      ehea_dump(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
- #endif
-       return hret;
- }
---- a/drivers/net/ehea/ehea_qmr.c
-+++ b/drivers/net/ehea/ehea_qmr.c
-@@ -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,171 @@ 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 void ehea_rebuild_busmap(void)
-+{
-+      u64 vaddr = EHEA_BUSMAP_START;
-+      int top, dir, idx;
-+
-+      for (top = 0; top < EHEA_MAP_ENTRIES; top++) {
-+              struct ehea_top_bmap *ehea_top;
-+              int valid_dir_entries = 0;
-+
-+              if (!ehea_bmap->top[top])
-+                      continue;
-+              ehea_top = ehea_bmap->top[top];
-+              for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) {
-+                      struct ehea_dir_bmap *ehea_dir;
-+                      int valid_entries = 0;
-+
-+                      if (!ehea_top->dir[dir])
-+                              continue;
-+                      valid_dir_entries++;
-+                      ehea_dir = ehea_top->dir[dir];
-+                      for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
-+                              if (!ehea_dir->ent[idx])
-+                                      continue;
-+                              valid_entries++;
-+                              ehea_dir->ent[idx] = vaddr;
-+                              vaddr += EHEA_SECTSIZE;
-+                      }
-+                      if (!valid_entries) {
-+                              ehea_top->dir[dir] = NULL;
-+                              kfree(ehea_dir);
-+                      }
-+              }
-+              if (!valid_dir_entries) {
-+                      ehea_bmap->top[top] = NULL;
-+                      kfree(ehea_top);
-+              }
-+      }
-+}
-+
-+static int ehea_update_busmap(unsigned long pfn, unsigned long nr_pages, int add)
- {
--      unsigned long i, mr_len, start_section, end_section;
-+      unsigned long i, start_section, end_section;
-+
-+      if (!nr_pages)
-+              return 0;
-+
-+      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 + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
--      mr_len = *(unsigned long *)arg;
-+      /* Mark entries as valid or invalid only; address is assigned later */
-+      for (i = start_section; i < end_section; i++) {
-+              u64 flag;
-+              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)
-+                              return ret;
-+                      flag = 1; /* valid */
-+                      ehea_mr_len += EHEA_SECTSIZE;
-+              } else {
-+                      if (!ehea_bmap->top[top])
-+                              continue;
-+                      if (!ehea_bmap->top[top]->dir[dir])
-+                              continue;
-+                      flag = 0; /* invalid */
-+                      ehea_mr_len -= EHEA_SECTSIZE;
-+              }
--      ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
--      if (!ehea_bmap)
--              return -ENOMEM;
-+              ehea_bmap->top[top]->dir[dir]->ent[idx] = flag;
-+      }
-+      ehea_rebuild_busmap(); /* Assign contiguous addresses for mr */
-+      return 0;
-+}
--      for (i = start_section; i < end_section; i++) {
--              int ret;
--              int top, dir, idx;
--              u64 vaddr;
-+int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages)
-+{
-+      int ret;
--              top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
--              dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
-+      mutex_lock(&ehea_busmap_mutex);
-+      ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
-+      mutex_unlock(&ehea_busmap_mutex);
-+      return ret;
-+}
--              ret = ehea_init_bmap(ehea_bmap, top, dir);
--              if(ret)
--                      return ret;
-+int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages)
-+{
-+      int ret;
--              idx = i & EHEA_INDEX_MASK;
--              vaddr = EHEA_BUSMAP_START + mr_len + i * EHEA_SECTSIZE;
-+      mutex_lock(&ehea_busmap_mutex);
-+      ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_REM_SECT);
-+      mutex_unlock(&ehea_busmap_mutex);
-+      return ret;
-+}
--              ehea_bmap->top[top]->dir[dir]->ent[idx] = vaddr;
--      }
-+static int ehea_is_hugepage(unsigned long pfn)
-+{
-+      int page_order;
--      mr_len += nr_pages * PAGE_SIZE;
--      *(unsigned long *)arg = mr_len;
-+      if (pfn & EHEA_HUGEPAGE_PFN_MASK)
-+              return 0;
--      return 0;
-+      page_order = compound_order(pfn_to_page(pfn));
-+      if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT)
-+              return 0;
-+
-+      return 1;
- }
--static unsigned long ehea_mr_len;
-+static int ehea_create_busmap_callback(unsigned long initial_pfn,
-+                                     unsigned long total_nr_pages, void *arg)
-+{
-+      int ret;
-+      unsigned long pfn, start_pfn, end_pfn, nr_pages;
--static DEFINE_MUTEX(ehea_busmap_mutex);
-+      if ((total_nr_pages * PAGE_SIZE) < EHEA_HUGEPAGE_SIZE)
-+              return ehea_update_busmap(initial_pfn, total_nr_pages,
-+                                        EHEA_BUSMAP_ADD_SECT);
-+
-+      /* Given chunk is >= 16GB -> check for hugepages */
-+      start_pfn = initial_pfn;
-+      end_pfn = initial_pfn + total_nr_pages;
-+      pfn = start_pfn;
-+
-+      while (pfn < end_pfn) {
-+              if (ehea_is_hugepage(pfn)) {
-+                      /* Add mem found in front of the hugepage */
-+                      nr_pages = pfn - start_pfn;
-+                      ret = ehea_update_busmap(start_pfn, nr_pages,
-+                                               EHEA_BUSMAP_ADD_SECT);
-+                      if (ret)
-+                              return ret;
-+
-+                      /* Skip the hugepage */
-+                      pfn += (EHEA_HUGEPAGE_SIZE / PAGE_SIZE);
-+                      start_pfn = pfn;
-+              } else
-+                      pfn += (EHEA_SECTSIZE / PAGE_SIZE);
-+      }
-+
-+      /* Add mem found behind the hugepage(s)  */
-+      nr_pages = pfn - start_pfn;
-+      return ehea_update_busmap(start_pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
-+}
- int ehea_create_busmap(void)
- {
-       int ret;
-+
-       mutex_lock(&ehea_busmap_mutex);
-       ehea_mr_len = 0;
--      ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, &ehea_mr_len,
-+      ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
-                                  ehea_create_busmap_callback);
-       mutex_unlock(&ehea_busmap_mutex);
-       return ret;
---- a/drivers/net/ehea/ehea_qmr.h
-+++ b/drivers/net/ehea/ehea_qmr.h
-@@ -40,6 +40,9 @@
- #define EHEA_PAGESIZE          (1UL << EHEA_PAGESHIFT)
- #define EHEA_SECTSIZE          (1UL << 24)
- #define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> EHEA_PAGESHIFT)
-+#define EHEA_HUGEPAGESHIFT     34
-+#define EHEA_HUGEPAGE_SIZE     (1UL << EHEA_HUGEPAGESHIFT)
-+#define EHEA_HUGEPAGE_PFN_MASK ((EHEA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
- #if ((1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE)
- #error eHEA module cannot work if kernel sectionsize < ehea sectionsize
-@@ -378,6 +381,8 @@ int ehea_rem_mr(struct ehea_mr *mr);
- void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
-+int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages);
-+int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages);
- int ehea_create_busmap(void);
- void ehea_destroy_busmap(void);
- u64 ehea_map_vaddr(void *caddr);