Re: [PATCH 1/2][RESEND] ehea: error handling improvement

2010-04-23 Thread Thomas Klein

On 04/22/2010 07:36 AM, David Miller wrote:

From: Thomas Kleintkl...@de.ibm.com
Date: Wed, 21 Apr 2010 11:10:55 +0200


Reset a port's resources only if they're actually in an error state

Signed-off-by: Thomas Kleintkl...@de.ibm.com
---

Patch created against net-2.6


I thought you were sorry for wasting my time and that you were going
to follow the directions I gave you last time, and I quote:


3) These are not appropriate for net-2.6 as we are deep in
the -rcX series at this point and only the most diabolical
bug fixes are appropriate.  Therefore, please generate these
against net-next-2.6, thanks.


And here you are generating your patches against net-2.6.  Heck, you
even feel it's worth mentioning explicitly.


Guilty! Allows no excuse. Screwed it. Deeply sorry.



Lucky for you the patches happen to apply cleanly to net-next-2.6 so
I've put them there.


Thanks!
Thomas


--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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


[PATCH 1/2][RESEND] ehea: error handling improvement

2010-04-21 Thread Thomas Klein
Reset a port's resources only if they're actually in an error state

Signed-off-by: Thomas Klein tkl...@de.ibm.com
---

Patch created against net-2.6

diff -Nurp net-2.6.orig/drivers/net/ehea/ehea_main.c 
net-2.6/drivers/net/ehea/ehea_main.c
--- net-2.6.orig/drivers/net/ehea/ehea_main.c   2010-04-21 10:23:21.0 
+0200
+++ net-2.6/drivers/net/ehea/ehea_main.c2010-04-21 10:41:21.0 
+0200
@@ -791,11 +791,17 @@ static struct ehea_cqe *ehea_proc_cqes(s
cqe_counter++;
rmb();
if (cqe-status  EHEA_CQE_STAT_ERR_MASK) {
-   ehea_error(Send Completion Error: Resetting port);
+   ehea_error(Bad send completion status=0x%04X,
+  cqe-status);
+
if (netif_msg_tx_err(pr-port))
ehea_dump(cqe, sizeof(*cqe), Send CQE);
-   ehea_schedule_port_reset(pr-port);
-   break;
+
+   if (cqe-status  EHEA_CQE_STAT_RESET_MASK) {
+   ehea_error(Resetting port);
+   ehea_schedule_port_reset(pr-port);
+   break;
+   }
}
 
if (netif_msg_tx_done(pr-port))
@@ -901,6 +907,8 @@ static irqreturn_t ehea_qp_aff_irq_handl
struct ehea_eqe *eqe;
struct ehea_qp *qp;
u32 qp_token;
+   u64 resource_type, aer, aerr;
+   int reset_port = 0;
 
eqe = ehea_poll_eq(port-qp_eq);
 
@@ -910,11 +918,24 @@ static irqreturn_t ehea_qp_aff_irq_handl
   eqe-entry, qp_token);
 
qp = port-port_res[qp_token].qp;
-   ehea_error_data(port-adapter, qp-fw_handle);
+
+   resource_type = ehea_error_data(port-adapter, qp-fw_handle,
+   aer, aerr);
+
+   if (resource_type == EHEA_AER_RESTYPE_QP) {
+   if ((aer  EHEA_AER_RESET_MASK) ||
+   (aerr  EHEA_AERR_RESET_MASK))
+reset_port = 1;
+   } else
+   reset_port = 1;   /* Reset in case of CQ or EQ error */
+
eqe = ehea_poll_eq(port-qp_eq);
}
 
-   ehea_schedule_port_reset(port);
+   if (reset_port) {
+   ehea_error(Resetting port);
+   ehea_schedule_port_reset(port);
+   }
 
return IRQ_HANDLED;
 }
diff -Nurp net-2.6.orig/drivers/net/ehea/ehea_qmr.c 
net-2.6/drivers/net/ehea/ehea_qmr.c
--- net-2.6.orig/drivers/net/ehea/ehea_qmr.c2010-04-21 10:23:21.0 
+0200
+++ net-2.6/drivers/net/ehea/ehea_qmr.c 2010-04-21 10:41:21.0 +0200
@@ -229,14 +229,14 @@ u64 ehea_destroy_cq_res(struct ehea_cq *
 
 int ehea_destroy_cq(struct ehea_cq *cq)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!cq)
return 0;
 
hcp_epas_dtor(cq-epas);
hret = ehea_destroy_cq_res(cq, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(cq-adapter, cq-fw_handle);
+   ehea_error_data(cq-adapter, cq-fw_handle, aer, aerr);
hret = ehea_destroy_cq_res(cq, FORCE_FREE);
}
 
@@ -357,7 +357,7 @@ u64 ehea_destroy_eq_res(struct ehea_eq *
 
 int ehea_destroy_eq(struct ehea_eq *eq)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!eq)
return 0;
 
@@ -365,7 +365,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
 
hret = ehea_destroy_eq_res(eq, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(eq-adapter, eq-fw_handle);
+   ehea_error_data(eq-adapter, eq-fw_handle, aer, aerr);
hret = ehea_destroy_eq_res(eq, FORCE_FREE);
}
 
@@ -540,7 +540,7 @@ u64 ehea_destroy_qp_res(struct ehea_qp *
 
 int ehea_destroy_qp(struct ehea_qp *qp)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!qp)
return 0;
 
@@ -548,7 +548,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
 
hret = ehea_destroy_qp_res(qp, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(qp-adapter, qp-fw_handle);
+   ehea_error_data(qp-adapter, qp-fw_handle, aer, aerr);
hret = ehea_destroy_qp_res(qp, FORCE_FREE);
}
 
@@ -986,42 +986,45 @@ void print_error_data(u64 *data)
if (length  EHEA_PAGESIZE)
length = EHEA_PAGESIZE;
 
-   if (type == 0x8) /* Queue Pair */
+   if (type == EHEA_AER_RESTYPE_QP)
ehea_error(QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, 
   port=%llX, resource, data[6], data[12], data[22]);
-
-   if (type == 0x4) /* Completion Queue */
+   else if (type == EHEA_AER_RESTYPE_CQ)
ehea_error(CQ (resource=%llX) state: AER=0x%llX, resource,
   data[6

[PATCH 2/2][RESEND] ehea: fix possible DLPAR/mem deadlock

2010-04-21 Thread Thomas Klein
Force serialization of userspace-triggered DLPAR/mem operations

Signed-off-by: Thomas Klein tkl...@de.ibm.com
---

Patch created against net-2.6

diff -Nurp net-2.6.orig/drivers/net/ehea/ehea.h net-2.6/drivers/net/ehea/ehea.h
--- net-2.6.orig/drivers/net/ehea/ehea.h2010-04-21 10:23:21.0 
+0200
+++ net-2.6/drivers/net/ehea/ehea.h 2010-04-21 10:42:14.0 +0200
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0102
+#define DRV_VERSIONEHEA_0103
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp net-2.6.orig/drivers/net/ehea/ehea_main.c 
net-2.6/drivers/net/ehea/ehea_main.c
--- net-2.6.orig/drivers/net/ehea/ehea_main.c   2010-04-21 10:43:14.0 
+0200
+++ net-2.6/drivers/net/ehea/ehea_main.c2010-04-21 10:42:14.0 
+0200
@@ -2889,7 +2889,6 @@ static void ehea_rereg_mrs(struct work_s
int ret, i;
struct ehea_adapter *adapter;
 
-   mutex_lock(dlpar_mem_lock);
ehea_info(LPAR memory changed - re-initializing driver);
 
list_for_each_entry(adapter, adapter_list, list)
@@ -2959,7 +2958,6 @@ static void ehea_rereg_mrs(struct work_s
}
ehea_info(re-initializing driver complete);
 out:
-   mutex_unlock(dlpar_mem_lock);
return;
 }
 
@@ -3542,7 +3540,14 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   int ret = NOTIFY_BAD;
struct memory_notify *arg = data;
+
+   if (!mutex_trylock(dlpar_mem_lock)) {
+   ehea_info(ehea_mem_notifier must not be called parallelized);
+   goto out;
+   }
+
switch (action) {
case MEM_CANCEL_OFFLINE:
ehea_info(memory offlining canceled);
@@ -3551,14 +3556,14 @@ static int ehea_mem_notifier(struct noti
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;
+   goto out_unlock;
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;
+   goto out_unlock;
ehea_rereg_mrs(NULL);
break;
default:
@@ -3566,8 +3571,12 @@ static int ehea_mem_notifier(struct noti
}
 
ehea_update_firmware_handles();
+   ret = NOTIFY_OK;
 
-   return NOTIFY_OK;
+out_unlock:
+   mutex_unlock(dlpar_mem_lock);
+out:
+   return ret;
 }
 
 static struct notifier_block ehea_mem_nb = {
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/2] ehea: error handling improvement

2010-04-19 Thread Thomas Klein

Reset a port's resources only if they're actually in an error state

Signed-off-by: Thomas Klein tkl...@de.ibm.com
---

Patch created against 2.6.34-rc4

diff -Nurp linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_main.c 
linux-2.6.34-rc4//drivers/net/ehea/ehea_main.c
--- linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_main.c 2010-04-19 
11:54:07.0 +0200
+++ linux-2.6.34-rc4//drivers/net/ehea/ehea_main.c  2010-04-19 
11:55:43.0 +0200
@@ -791,11 +791,17 @@ static struct ehea_cqe *ehea_proc_cqes(s
cqe_counter++;
rmb();
if (cqe-status  EHEA_CQE_STAT_ERR_MASK) {
-   ehea_error(Send Completion Error: Resetting port);
+   ehea_error(Bad send completion status=0x%04X,
+  cqe-status);
+
if (netif_msg_tx_err(pr-port))
ehea_dump(cqe, sizeof(*cqe), Send CQE);
-   ehea_schedule_port_reset(pr-port);
-   break;
+
+   if (cqe-status  EHEA_CQE_STAT_RESET_MASK) {
+   ehea_error(Resetting port);
+   ehea_schedule_port_reset(pr-port);
+   break;
+   }
}

if (netif_msg_tx_done(pr-port))
@@ -901,6 +907,8 @@ static irqreturn_t ehea_qp_aff_irq_handl
struct ehea_eqe *eqe;
struct ehea_qp *qp;
u32 qp_token;
+   u64 resource_type, aer, aerr;
+   int reset_port = 0;

eqe = ehea_poll_eq(port-qp_eq);

@@ -910,11 +918,24 @@ static irqreturn_t ehea_qp_aff_irq_handl
   eqe-entry, qp_token);

qp = port-port_res[qp_token].qp;
-   ehea_error_data(port-adapter, qp-fw_handle);
+
+   resource_type = ehea_error_data(port-adapter, qp-fw_handle,
+   aer, aerr);
+
+   if (resource_type == EHEA_AER_RESTYPE_QP) {
+   if ((aer  EHEA_AER_RESET_MASK) ||
+   (aerr  EHEA_AERR_RESET_MASK))
+reset_port = 1;
+   } else
+   reset_port = 1;   /* Reset in case of CQ or EQ error */
+
eqe = ehea_poll_eq(port-qp_eq);
}

-   ehea_schedule_port_reset(port);
+   if (reset_port) {
+   ehea_error(Resetting port);
+   ehea_schedule_port_reset(port);
+   }

return IRQ_HANDLED;
 }
diff -Nurp linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_qmr.c 
linux-2.6.34-rc4//drivers/net/ehea/ehea_qmr.c
--- linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_qmr.c  2010-04-19 
11:54:07.0 +0200
+++ linux-2.6.34-rc4//drivers/net/ehea/ehea_qmr.c   2010-04-19 
11:56:36.0 +0200
@@ -229,14 +229,14 @@ u64 ehea_destroy_cq_res(struct ehea_cq *

 int ehea_destroy_cq(struct ehea_cq *cq)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!cq)
return 0;

hcp_epas_dtor(cq-epas);
hret = ehea_destroy_cq_res(cq, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(cq-adapter, cq-fw_handle);
+   ehea_error_data(cq-adapter, cq-fw_handle, aer, aerr);
hret = ehea_destroy_cq_res(cq, FORCE_FREE);
}

@@ -357,7 +357,7 @@ u64 ehea_destroy_eq_res(struct ehea_eq *

 int ehea_destroy_eq(struct ehea_eq *eq)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!eq)
return 0;

@@ -365,7 +365,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)

hret = ehea_destroy_eq_res(eq, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(eq-adapter, eq-fw_handle);
+   ehea_error_data(eq-adapter, eq-fw_handle, aer, aerr);
hret = ehea_destroy_eq_res(eq, FORCE_FREE);
}

@@ -540,7 +540,7 @@ u64 ehea_destroy_qp_res(struct ehea_qp *

 int ehea_destroy_qp(struct ehea_qp *qp)
 {
-   u64 hret;
+   u64 hret, aer, aerr;
if (!qp)
return 0;

@@ -548,7 +548,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)

hret = ehea_destroy_qp_res(qp, NORMAL_FREE);
if (hret == H_R_STATE) {
-   ehea_error_data(qp-adapter, qp-fw_handle);
+   ehea_error_data(qp-adapter, qp-fw_handle, aer, aerr);
hret = ehea_destroy_qp_res(qp, FORCE_FREE);
}

@@ -986,42 +986,45 @@ void print_error_data(u64 *data)
if (length  EHEA_PAGESIZE)
length = EHEA_PAGESIZE;

-   if (type == 0x8) /* Queue Pair */
+   if (type == EHEA_AER_RESTYPE_QP)
ehea_error(QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, 
   port=%llX, resource, data[6], data[12], data[22]);
-
-   if (type == 0x4) /* Completion Queue */
+   else if (type == EHEA_AER_RESTYPE_CQ)
ehea_error(CQ (resource=%llX) state: AER=0x

[PATCH 2/2] ehea: fix possible DLPAR/mem deadlock

2010-04-19 Thread Thomas Klein

Force serialization of userspace-triggered DLPAR/mem operations

Signed-off-by: Thomas Klein tkl...@de.ibm.com
---

Patch created against 2.6.34-rc4

diff -Nurp linux-2.6.34-rc4.orig//drivers/net/ehea/ehea.h 
linux-2.6.34-rc4//drivers/net/ehea/ehea.h
--- linux-2.6.34-rc4.orig//drivers/net/ehea/ehea.h  2010-04-19 
11:54:07.0 +0200
+++ linux-2.6.34-rc4//drivers/net/ehea/ehea.h   2010-04-19 12:00:14.0 
+0200
@@ -40,7 +40,7 @@
 #include asm/io.h

 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0102
+#define DRV_VERSIONEHEA_0103

 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_main.c 
linux-2.6.34-rc4//drivers/net/ehea/ehea_main.c
--- linux-2.6.34-rc4.orig//drivers/net/ehea/ehea_main.c 2010-04-19 
11:59:11.0 +0200
+++ linux-2.6.34-rc4//drivers/net/ehea/ehea_main.c  2010-04-19 
11:59:50.0 +0200
@@ -2889,7 +2889,6 @@ static void ehea_rereg_mrs(struct work_s
int ret, i;
struct ehea_adapter *adapter;

-   mutex_lock(dlpar_mem_lock);
ehea_info(LPAR memory changed - re-initializing driver);

list_for_each_entry(adapter, adapter_list, list)
@@ -2959,7 +2958,6 @@ static void ehea_rereg_mrs(struct work_s
}
ehea_info(re-initializing driver complete);
 out:
-   mutex_unlock(dlpar_mem_lock);
return;
 }

@@ -3542,7 +3540,14 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   int ret = NOTIFY_BAD;
struct memory_notify *arg = data;
+
+   if (!mutex_trylock(dlpar_mem_lock)) {
+   ehea_info(ehea_mem_notifier must not be called parallelized);
+   goto out;
+   }
+
switch (action) {
case MEM_CANCEL_OFFLINE:
ehea_info(memory offlining canceled);
@@ -3551,14 +3556,14 @@ static int ehea_mem_notifier(struct noti
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;
+   goto out_unlock;
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;
+   goto out_unlock;
ehea_rereg_mrs(NULL);
break;
default:
@@ -3566,8 +3571,12 @@ static int ehea_mem_notifier(struct noti
}

ehea_update_firmware_handles();
+   ret = NOTIFY_OK;

-   return NOTIFY_OK;
+out_unlock:
+   mutex_unlock(dlpar_mem_lock);
+out:
+   return ret;
 }

 static struct notifier_block ehea_mem_nb = {
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] powerpc: Move ehea hcall definitions into hvcall.h

2009-10-22 Thread Thomas Klein
Anton Blanchard wrote:
 Move ehea hcall definitions into hvcall.h.
 
 Signed-off-by: Anton Blanchard an...@samba.org

Acked-by: Thomas Klein tkl...@de.ibm.com

 ---
 
 Index: linux.trees.git/arch/powerpc/include/asm/hvcall.h
 ===
 --- linux.trees.git.orig/arch/powerpc/include/asm/hvcall.h2009-10-19 
 17:59:42.0 +1100
 +++ linux.trees.git/arch/powerpc/include/asm/hvcall.h 2009-10-19 
 18:03:18.0 +1100
 @@ -212,6 +212,19 @@
  #define H_QUERY_INT_STATE   0x1E4
  #define H_POLL_PENDING   0x1D8
  #define H_ILLAN_ATTRIBUTES   0x244
 +#define H_MODIFY_HEA_QP  0x250
 +#define H_QUERY_HEA_QP   0x254
 +#define H_QUERY_HEA  0x258
 +#define H_QUERY_HEA_PORT 0x25C
 +#define H_MODIFY_HEA_PORT0x260
 +#define H_REG_BCMC   0x264
 +#define H_DEREG_BCMC 0x268
 +#define H_REGISTER_HEA_RPAGES0x26C
 +#define H_DISABLE_AND_GET_HEA0x270
 +#define H_GET_HEA_INFO   0x274
 +#define H_ALLOC_HEA_RESOURCE 0x278
 +#define H_ADD_CONN   0x284
 +#define H_DEL_CONN   0x288
  #define H_JOIN   0x298
  #define H_VASI_STATE0x2A4
  #define H_ENABLE_CRQ 0x2B0
 Index: linux.trees.git/drivers/net/ehea/ehea_phyp.h
 ===
 --- linux.trees.git.orig/drivers/net/ehea/ehea_phyp.h 2009-10-19 
 18:03:48.0 +1100
 +++ linux.trees.git/drivers/net/ehea/ehea_phyp.h  2009-10-19 
 18:03:56.0 +1100
 @@ -33,7 +33,6 @@
  #include asm/hvcall.h
  #include ehea.h
  #include ehea_hw.h
 -#include ehea_hcall.h
 
  /* Some abbreviations used here:
   *
 Index: linux.trees.git/drivers/net/ehea/ehea_hcall.h
 ===
 --- linux.trees.git.orig/drivers/net/ehea/ehea_hcall.h2009-10-19 
 17:59:31.0 +1100
 +++ /dev/null 1970-01-01 00:00:00.0 +
 @@ -1,51 +0,0 @@
 -/*
 - *  linux/drivers/net/ehea/ehea_hcall.h
 - *
 - *  eHEA ethernet device driver for IBM eServer System p
 - *
 - *  (C) Copyright IBM Corp. 2006
 - *
 - *  Authors:
 - *   Christoph Raisch rai...@de.ibm.com
 - *   Jan-Bernd Themann them...@de.ibm.com
 - *   Thomas Klein tkl...@de.ibm.com
 - *
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2, or (at your option)
 - * any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
 - * GNU General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 - */
 -
 -#ifndef __EHEA_HCALL_H__
 -#define __EHEA_HCALL_H__
 -
 -/**
 - * This file contains HCALL defines that are to be included in the 
 appropriate
 - * kernel files later
 - */
 -
 -#define H_ALLOC_HEA_RESOURCE   0x278
 -#define H_MODIFY_HEA_QP0x250
 -#define H_QUERY_HEA_QP 0x254
 -#define H_QUERY_HEA0x258
 -#define H_QUERY_HEA_PORT   0x25C
 -#define H_MODIFY_HEA_PORT  0x260
 -#define H_REG_BCMC 0x264
 -#define H_DEREG_BCMC   0x268
 -#define H_REGISTER_HEA_RPAGES  0x26C
 -#define H_DISABLE_AND_GET_HEA  0x270
 -#define H_GET_HEA_INFO 0x274
 -#define H_ADD_CONN 0x284
 -#define H_DEL_CONN 0x288
 -
 -#endif   /* __EHEA_HCALL_H__ */
 ___
 Linuxppc-dev mailing list
 Linuxppc-dev@lists.ozlabs.org
 https://lists.ozlabs.org/listinfo/linuxppc-dev

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


[PATCH] ehea: Fix memory hotplug handling

2009-02-19 Thread Thomas Klein
Added missing set_bit() to disable data transfer when a memchange notification 
is handled

Signed-off-by: Thomas Klein tkl...@de.ibm.com
---
diff -Nurp -X dontdiff linux-2.6.29-rc4/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.29-rc4/drivers/net/ehea/ehea.h2009-02-18 16:59:54.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2009-02-18 17:01:12.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0098
+#define DRV_VERSIONEHEA_0099
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.29-rc4/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.29-rc4/drivers/net/ehea/ehea_main.c   2009-02-18 
16:59:54.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2009-02-18 17:01:12.0 
+0100
@@ -3517,12 +3517,14 @@ static int ehea_mem_notifier(struct noti
/* 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);
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/3] ehea: Use net_device_ops structure

2009-01-21 Thread Thomas Klein
Adapt to lately introduced net_device_ops structure.

Signed-off-by: Thomas Klein tkl...@de.ibm.com

---
diff -Nurp -X dontdiff linux-2.6.29/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.29/drivers/net/ehea/ehea.h2009-01-16 12:03:27.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2009-01-20 15:10:28.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0096
+#define DRV_VERSIONEHEA_0097
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.29/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.29/drivers/net/ehea/ehea_main.c   2009-01-16 12:03:27.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2009-01-20 15:10:28.0 
+0100
@@ -3069,6 +3069,22 @@ static void ehea_unregister_port(struct
of_device_unregister(port-ofdev);
 }
 
+static const struct net_device_ops ehea_netdev_ops = {
+   .ndo_open   = ehea_open,
+   .ndo_stop   = ehea_stop,
+   .ndo_start_xmit = ehea_start_xmit,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+   .ndo_poll_controller= ehea_netpoll,
+#endif
+   .ndo_get_stats  = ehea_get_stats,
+   .ndo_set_mac_address= ehea_set_mac_addr,
+   .ndo_set_multicast_list = ehea_set_multicast_list,
+   .ndo_change_mtu = ehea_change_mtu,
+   .ndo_vlan_rx_register   = ehea_vlan_rx_register,
+   .ndo_vlan_rx_add_vid= ehea_vlan_rx_add_vid,
+   .ndo_vlan_rx_kill_vid   = ehea_vlan_rx_kill_vid
+};
+
 struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 u32 logical_port_id,
 struct device_node *dn)
@@ -3121,19 +3137,9 @@ struct ehea_port *ehea_setup_single_port
/* initialize net_device structure */
memcpy(dev-dev_addr, port-mac_addr, ETH_ALEN);
 
-   dev-open = ehea_open;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-   dev-poll_controller = ehea_netpoll;
-#endif
-   dev-stop = ehea_stop;
-   dev-hard_start_xmit = ehea_start_xmit;
-   dev-get_stats = ehea_get_stats;
-   dev-set_multicast_list = ehea_set_multicast_list;
-   dev-set_mac_address = ehea_set_mac_addr;
-   dev-change_mtu = ehea_change_mtu;
-   dev-vlan_rx_register = ehea_vlan_rx_register;
-   dev-vlan_rx_add_vid = ehea_vlan_rx_add_vid;
-   dev-vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
+   dev-netdev_ops = ehea_netdev_ops;
+   ehea_set_ethtool_ops(dev);
+
dev-features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
  | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
  | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
@@ -3142,7 +3148,6 @@ struct ehea_port *ehea_setup_single_port
dev-watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
INIT_WORK(port-reset_task, ehea_reset_port);
-   ehea_set_ethtool_ops(dev);
 
ret = register_netdev(dev);
if (ret) {
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/3] ehea: Fix mem allocations which require page alignment

2009-01-21 Thread Thomas Klein
PAGE_SIZE allocations via slab are not guaranteed to be page-aligned. Fixed
all memory allocations where page alignment is required by firmware.

Signed-off-by: Thomas Klein tkl...@de.ibm.com

---
Thanks to Nathan Lynch for this hint!

diff -Nurp -X dontdiff linux-2.6.29-rc2/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.29-rc2/drivers/net/ehea/ehea_main.c   2009-01-21 
13:24:54.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2009-01-21 13:36:14.0 
+0100
@@ -308,7 +308,7 @@ static struct net_device_stats *ehea_get
 
memset(stats, 0, sizeof(*stats));
 
-   cb2 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+   cb2 = (void *)get_zeroed_page(GFP_ATOMIC);
if (!cb2) {
ehea_error(no mem for cb2);
goto out;
@@ -341,7 +341,7 @@ static struct net_device_stats *ehea_get
stats-rx_packets = rx_packets;
 
 out_herr:
-   kfree(cb2);
+   free_page((unsigned long)cb2);
 out:
return stats;
 }
@@ -915,7 +915,7 @@ int ehea_sense_port_attr(struct ehea_por
struct hcp_ehea_port_cb0 *cb0;
 
/* may be called via ehea_neq_tasklet() */
-   cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+   cb0 = (void *)get_zeroed_page(GFP_ATOMIC);
if (!cb0) {
ehea_error(no mem for cb0);
ret = -ENOMEM;
@@ -996,7 +996,7 @@ int ehea_sense_port_attr(struct ehea_por
 out_free:
if (ret || netif_msg_probe(port))
ehea_dump(cb0, sizeof(*cb0), ehea_sense_port_attr);
-   kfree(cb0);
+   free_page((unsigned long)cb0);
 out:
return ret;
 }
@@ -1007,7 +1007,7 @@ int ehea_set_portspeed(struct ehea_port
u64 hret;
int ret = 0;
 
-   cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb4 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb4) {
ehea_error(no mem for cb4);
ret = -ENOMEM;
@@ -1075,7 +1075,7 @@ int ehea_set_portspeed(struct ehea_port
if (!prop_carrier_state || (port-phy_link == EHEA_PHY_LINK_UP))
netif_carrier_on(port-netdev);
 
-   kfree(cb4);
+   free_page((unsigned long)cb4);
 out:
return ret;
 }
@@ -1302,7 +1302,7 @@ static int ehea_configure_port(struct eh
struct hcp_ehea_port_cb0 *cb0;
 
ret = -ENOMEM;
-   cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb0 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb0)
goto out;
 
@@ -1338,7 +1338,7 @@ static int ehea_configure_port(struct eh
ret = 0;
 
 out_free:
-   kfree(cb0);
+   free_page((unsigned long)cb0);
 out:
return ret;
 }
@@ -1748,7 +1748,7 @@ static int ehea_set_mac_addr(struct net_
goto out;
}
 
-   cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb0 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb0) {
ehea_error(no mem for cb0);
ret = -ENOMEM;
@@ -1793,7 +1793,7 @@ out_upregs:
ehea_update_bcmc_registrations();
spin_unlock(ehea_bcmc_regs.lock);
 out_free:
-   kfree(cb0);
+   free_page((unsigned long)cb0);
 out:
return ret;
 }
@@ -1817,7 +1817,7 @@ static void ehea_promiscuous(struct net_
if ((enable  port-promisc) || (!enable  !port-promisc))
return;
 
-   cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+   cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
if (!cb7) {
ehea_error(no mem for cb7);
goto out;
@@ -1836,7 +1836,7 @@ static void ehea_promiscuous(struct net_
 
port-promisc = enable;
 out:
-   kfree(cb7);
+   free_page((unsigned long)cb7);
return;
 }
 
@@ -2217,7 +2217,7 @@ static void ehea_vlan_rx_register(struct
 
port-vgrp = grp;
 
-   cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb1 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb1) {
ehea_error(no mem for cb1);
goto out;
@@ -2228,7 +2228,7 @@ static void ehea_vlan_rx_register(struct
if (hret != H_SUCCESS)
ehea_error(modify_ehea_port failed);
 
-   kfree(cb1);
+   free_page((unsigned long)cb1);
 out:
return;
 }
@@ -2241,7 +2241,7 @@ static void ehea_vlan_rx_add_vid(struct
int index;
u64 hret;
 
-   cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb1 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb1) {
ehea_error(no mem for cb1);
goto out;
@@ -2262,7 +2262,7 @@ static void ehea_vlan_rx_add_vid(struct
if (hret != H_SUCCESS)
ehea_error(modify_ehea_port failed);
 out:
-   kfree(cb1);
+   free_page((unsigned long)cb1);
return;
 }
 
@@ -2276,7 +2276,7 @@ static void ehea_vlan_rx_kill_vid(struct
 
vlan_group_set_device(port-vgrp, vid, NULL);
 
-   cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+   cb1 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb1) {
ehea_error(no mem

[PATCH 3/3] ehea: Improve driver behaviour in low mem conditions

2009-01-21 Thread Thomas Klein
Reworked receive queue fill policies to make the driver more tolerant
in low memory conditions.

Signed-off-by: Thomas Klein tkl...@de.ibm.com

---
diff -Nurp -X dontdiff linux-2.6.29-rc2/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.29-rc2/drivers/net/ehea/ehea_main.c   2009-01-20 
17:03:17.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2009-01-20 17:03:57.0 
+0100
@@ -370,8 +370,6 @@ static void ehea_refill_rq1(struct ehea_
  EHEA_L_PKT_SIZE);
if (!skb_arr_rq1[index]) {
pr-rq1_skba.os_skbs = fill_wqes - i;
-   ehea_error(%s: no mem for skb/%d wqes filled,
-  dev-name, i);
break;
}
}
@@ -387,26 +385,19 @@ static void ehea_refill_rq1(struct ehea_
ehea_update_rq1a(pr-qp, adder);
 }
 
-static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
+static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
 {
-   int ret = 0;
struct sk_buff **skb_arr_rq1 = pr-rq1_skba.arr;
struct net_device *dev = pr-port-netdev;
int i;
 
for (i = 0; i  pr-rq1_skba.len; i++) {
skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-   if (!skb_arr_rq1[i]) {
-   ehea_error(%s: no mem for skb/%d wqes filled,
-  dev-name, i);
-   ret = -ENOMEM;
-   goto out;
-   }
+   if (!skb_arr_rq1[i])
+   break;
}
/* Ring doorbell */
ehea_update_rq1a(pr-qp, nr_rq1a);
-out:
-   return ret;
 }
 
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
@@ -435,10 +426,12 @@ static int ehea_refill_rq_def(struct ehe
u64 tmp_addr;
struct sk_buff *skb = netdev_alloc_skb(dev, packet_size);
if (!skb) {
-   ehea_error(%s: no mem for skb/%d wqes filled,
-  pr-port-netdev-name, i);
q_skba-os_skbs = fill_wqes - i;
-   ret = -ENOMEM;
+   if (q_skba-os_skbs == q_skba-len - 2) {
+   ehea_info(%s: rq%i ran dry - no mem for skb,
+ pr-port-netdev-name, rq_nr);
+   ret = -ENOMEM;
+   }
break;
}
skb_reserve(skb, NET_IP_ALIGN);
@@ -1201,11 +1194,11 @@ static int ehea_fill_port_res(struct ehe
int ret;
struct ehea_qp_init_attr *init_attr = pr-qp-init_attr;
 
-   ret = ehea_init_fill_rq1(pr, init_attr-act_nr_rwqes_rq1
-- init_attr-act_nr_rwqes_rq2
-- init_attr-act_nr_rwqes_rq3 - 1);
+   ehea_init_fill_rq1(pr, init_attr-act_nr_rwqes_rq1
+  - init_attr-act_nr_rwqes_rq2
+  - init_attr-act_nr_rwqes_rq3 - 1);
 
-   ret |= ehea_refill_rq2(pr, init_attr-act_nr_rwqes_rq2 - 1);
+   ret = ehea_refill_rq2(pr, init_attr-act_nr_rwqes_rq2 - 1);
 
ret |= ehea_refill_rq3(pr, init_attr-act_nr_rwqes_rq3 - 1);
 
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] ehea: Add hugepage detection

2008-10-27 Thread Thomas Klein
Dave,

thanks for your valuable comments - see mine below. I'll send a reworked patch 
asap.

Thomas


On Friday 24 October 2008 08:55:37 pm you wrote:
 On Fri, 2008-10-24 at 13:07 +0200, Thomas Klein wrote:
  16GB hugepages may not be part of a memory region (firmware restriction). 
  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.
 
 Does this support a case where a userspace app is reading network
 packets into a 16GB page backed area?  I think you need to elaborate on
 what kind of memory you need to have registered in these memory regions.
 It's hard to review what you've done here otherwise.
 
  --- linux-2.6.27/drivers/net/ehea/ehea_qmr.c2008-10-24 
  09:29:19.0 +0200
  +++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-10-24 
  09:45:15.0 +0200
  @@ -636,6 +636,9 @@ static int ehea_update_busmap(unsigned l
   {
  unsigned long i, start_section, end_section;
  
  +   if (!pgnum)
  +   return 0;
 
 This probably needs a comment.  It's not obvious what it is doing.

I decided to just rename the var to nr_pages as it is used in all other
busmap-related functions in our code. That makes the condition check quite
obvious.

 
  if (!ehea_bmap) {
  ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
  if (!ehea_bmap)
  @@ -692,10 +695,47 @@ int ehea_rem_sect_bmap(unsigned long pfn
  return ret;
   }
  
  -static int ehea_create_busmap_callback(unsigned long pfn,
  -  unsigned long nr_pages, void *arg)
  +static int ehea_is_hugepage(unsigned long pfn)
  +{
  +   return pfn  PAGE_SHIFT)  (EHEA_HUGEPAGE_SIZE - 1)) == 0)
  +(compound_order(pfn_to_page(pfn)) + PAGE_SHIFT
  +   == EHEA_HUGEPAGESHIFT) );
  +}
 
 Whoa.  That's dense.  Can you actually read that in less than 5 minutes?
 Seriously.

Thanks for this comment. I totally agree - and I'm happy to aerate it a bit.
I had been urged to make it dense during our internal review ;-)

 
 I'm not sure what else you use EHEA_HUGEPAGE_SIZE for or if this gets
 duplicated, but this would look nicer if you just had a:
 
 #define EHEA_HUGEPAGE_PFN_MASK ((EHEA_HUGEPAGE_SIZE - 1)  PAGE_SHIFT)
 
   if (pfn  EHEA_HUGEPAGE_PFN_MASK)
   return 0;
 
 Or, with no new macro:
 
   if ((pfn  PAGE_SHIFT)  (EHEA_HUGEPAGE_SIZE - 1) != 0)
   return 0;
 
   page_order = compound_order(pfn_to_page(pfn));
   if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT)
   return 0;
   return 1;
 }
 
 Please break that up into something that is truly readable.  gcc will
 generate the exact same code.
 
  +static int ehea_create_busmap_callback(unsigned long initial_pfn,
  +  unsigned long total_nr_pages, void *arg)
   {
  -   return ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
  +   int ret;
  +   unsigned long pfn, start_pfn, end_pfn, nr_pages;
  +
  +   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)
  diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_qmr.h 
  patched_kernel/drivers/net/ehea/ehea_qmr.h
  --- linux-2.6.27/drivers/net/ehea/ehea_qmr.h2008-10-24 
  09:29:19.0 +0200
  +++ patched_kernel/drivers/net/ehea/ehea_qmr.h  2008-10-24 
  09:45:15.0 +0200
  @@ -40,6 +40,8 @@
   #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)
 
 I'm a bit worried that you're basically duplicating hugetlb.h here.  Why
 not just use the existing 16GB page macros?  While you're

[PATCH] ehea: Add hugepage detection

2008-10-27 Thread Thomas Klein
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.

Signed-off-by: Thomas Klein [EMAIL PROTECTED]
---
This reworked patch accounts for comments I got. It's 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-24 09:29:19.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-10-27 09:27:46.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h

 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0094
+#define DRV_VERSIONEHEA_0095

 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
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-24 09:29:19.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.c  2008-10-27 09:27:46.0 
+0100
@@ -632,10 +632,13 @@ static void ehea_rebuild_busmap(void)
}
 }

-static int ehea_update_busmap(unsigned long pfn, unsigned long pgnum, int add)
+static int ehea_update_busmap(unsigned long pfn, unsigned long nr_pages, int 
add)
 {
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)
@@ -643,7 +646,7 @@ static int ehea_update_busmap(unsigned l
}

start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
-   end_section = start_section + ((pgnum * PAGE_SIZE) / EHEA_SECTSIZE);
+   end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
/* Mark entries as valid or invalid only; address is assigned later */
for (i = start_section; i  end_section; i++) {
u64 flag;
@@ -692,10 +695,54 @@ int ehea_rem_sect_bmap(unsigned long pfn
return ret;
 }

-static int ehea_create_busmap_callback(unsigned long pfn,
-  unsigned long nr_pages, void *arg)
+static int ehea_is_hugepage(unsigned long pfn)
+{
+   int page_order;
+
+   if (pfn  EHEA_HUGEPAGE_PFN_MASK)
+   return 0;
+
+   page_order = compound_order(pfn_to_page(pfn));
+   if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT)
+   return 0;
+
+   return 1;
+}
+
+static int ehea_create_busmap_callback(unsigned long initial_pfn,
+  unsigned long total_nr_pages, void *arg)
 {
-   return ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
+   int ret;
+   unsigned long pfn, start_pfn, end_pfn, nr_pages;
+
+   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)
diff -Nurp -X dontdiff linux-2.6.27/drivers/net/ehea/ehea_qmr.h 
patched_kernel/drivers/net/ehea/ehea_qmr.h
--- linux-2.6.27/drivers/net/ehea/ehea_qmr.h2008-10-24 09:29:19.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea_qmr.h  2008-10-27 09:27:46.0 
+0100
@@ -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

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

2008-09-23 Thread Thomas Klein
Hannes Hering wrote:
 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, please apply.

Acked-by: Thomas Klein [EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2/2] ehea: fix mutex and spinlock use

2008-09-16 Thread Thomas Klein

Sebastien Dugue wrote:

On Mon, 15 Sep 2008 17:18:27 +0200 Thomas Klein [EMAIL PROTECTED] wrote:


NACK!

I regret but this patch is wrong. It is not sufficient to only lock
the replacement of an old list with a new list. Building up those
lists is a 3-step process:

1. Count the number of entries a list will contain and allocate mem
2. Fill the list
3. Replace old list with updated list

It's obvious that the contents of the list may not change during this
procedure. That means that not only the list build-up procedure must
be locked. It must be assured that no function that modifies the list's
content can be called while another list update is in progress.

Jeff, please revert this patch.


  OK, your call, you know the code better than I do.

  But the locking could at least be pushed into ehea_update_firmware_handles()
and ehea_update_bcmc_registrations() instead of being at each call site.

  Thanks,

  Sebastien.



It unfortunately can't. As I already mentioned it must be assured that no
function that modifies the list's content can be called while another list
update is in progress. This means that for example ehea_broadcast_reg_helper()
may not run during a list update. That's why the locks surround these function
calls as well.

Thomas



Thanks
Thomas



Sebastien Dugue wrote:

  Looks like to me that the ehea_fw_handles.lock mutex and the
ehea_bcmc_regs.lock spinlock are taken much longer than necessary and could
as well be pushed inside the functions that need them
(ehea_update_firmware_handles() and ehea_update_bcmc_registrations())
rather than at each callsite.

Signed-off-by: Sebastien Dugue [EMAIL PROTECTED]
---
 drivers/net/ehea/ehea_main.c |   26 --
 1 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index b70c531..c765ec6 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -219,9 +219,11 @@ static void ehea_update_firmware_handles(void)
}
 
 out_update:

+   mutex_lock(ehea_fw_handles.lock);
kfree(ehea_fw_handles.arr);
ehea_fw_handles.arr = arr;
ehea_fw_handles.num_entries = i;
+   mutex_unlock(ehea_fw_handles.lock);
 }
 
 static void ehea_update_bcmc_registrations(void)

@@ -293,9 +295,11 @@ static void ehea_update_bcmc_registrations(void)
}
 
 out_update:

+   spin_lock(ehea_bcmc_regs.lock);
kfree(ehea_bcmc_regs.arr);
ehea_bcmc_regs.arr = arr;
ehea_bcmc_regs.num_entries = i;
+   spin_unlock(ehea_bcmc_regs.lock);
 }
 
 static struct net_device_stats *ehea_get_stats(struct net_device *dev)

@@ -1770,8 +1774,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void 
*sa)
 
 	memcpy(dev-dev_addr, mac_addr-sa_data, dev-addr_len);
 
-	spin_lock(ehea_bcmc_regs.lock);

-
/* Deregister old MAC in pHYP */
if (port-state == EHEA_PORT_UP) {
ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
@@ -1792,7 +1794,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void 
*sa)
 
 out_upregs:

ehea_update_bcmc_registrations();
-   spin_unlock(ehea_bcmc_regs.lock);
 out_free:
kfree(cb0);
 out:
@@ -1954,8 +1955,6 @@ static void ehea_set_multicast_list(struct net_device 
*dev)
}
ehea_promiscuous(dev, 0);
 
-	spin_lock(ehea_bcmc_regs.lock);

-
if (dev-flags  IFF_ALLMULTI) {
ehea_allmulti(dev, 1);
goto out;
@@ -1985,7 +1984,6 @@ static void ehea_set_multicast_list(struct net_device 
*dev)
}
 out:
ehea_update_bcmc_registrations();
-   spin_unlock(ehea_bcmc_regs.lock);
return;
 }
 
@@ -2466,8 +2464,6 @@ static int ehea_up(struct net_device *dev)

if (port-state == EHEA_PORT_UP)
return 0;
 
-	mutex_lock(ehea_fw_handles.lock);

-
ret = ehea_port_res_setup(port, port-num_def_qps,
  port-num_add_tx_qps);
if (ret) {
@@ -2504,8 +2500,6 @@ static int ehea_up(struct net_device *dev)
}
}
 
-	spin_lock(ehea_bcmc_regs.lock);

-
ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
if (ret) {
ret = -EIO;
@@ -2527,10 +2521,8 @@ out:
ehea_info(Failed starting %s. ret=%i, dev-name, ret);
 
 	ehea_update_bcmc_registrations();

-   spin_unlock(ehea_bcmc_regs.lock);
 
 	ehea_update_firmware_handles();

-   mutex_unlock(ehea_fw_handles.lock);
 
 	return ret;

 }
@@ -2580,9 +2572,6 @@ static int ehea_down(struct net_device *dev)
if (port-state == EHEA_PORT_DOWN)
return 0;
 
-	mutex_lock(ehea_fw_handles.lock);

-
-   spin_lock(ehea_bcmc_regs.lock);
ehea_drop_multicast_list(dev);
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
@@ -2591,7 +2580,6 @@ static int ehea_down(struct net_device *dev)

port-state = EHEA_PORT_DOWN;
 
 	ehea_update_bcmc_registrations();

-   spin_unlock

Re: [PATCH HACK] powerpc: quick hack to get a functional eHEA with hardirq preemption

2008-09-15 Thread Thomas Klein

Hi,

we are a bit worried about putting this into the mainstream part of non real
time linux. There interrupts work perfectly fine, and it was a bit of a
challenge to get there for all cases / configurations / machines.

Could you try to enable these changes only for RT-Linux via a real-time
kconfig switch? This way we make sure we don't break the scheme for
eHEA / eHCA.

Regards,
Jan-Bernd, Christoph


Sebastien Dugue wrote:

WARNING: HACK - HACK - HACK

  Under the RT kernel (with hardirq preemption) the eHEA driver hangs right
after booting. Fiddling with the hardirqs and softirqs priorities allows to
run a bit longer but as soon as the network gets under load, the hang
returns. After investigating, it appears that the driver is loosing interrupts.

  To make a long story short, looking at the code, it appears that the XICS
maps all its interrupts to level sensitive interrupts (I don't know if it's the
reality or if it's due to an incomplete implementation - no datasheets
available to check) and use the fasteoi processing flow.

  When entering the low level handler, level sensitive interrupts are masked,
then eio'd in interrupt context and then unmasked at the end of hardirq
processing.
That's fine as any interrupt comming in-between will still be processed since
the kernel replays those pending interrupts.

  However, it appears that the eHEA interrupts are behaving as edge sensitive
interrupts and are routed through the XICS which process those as level
sensitive using the fasteoi handler __OR__ the XICS loses interrupts when they
are masked.

  Therefore the masking done in the handler causes any interrupt happening while
in the handler to be lost.

  So this patch maps the interrupts being requested through
ibmebus_request_irq() as edge sensitive interrupts (this concerns both the eHEA
and the eHCA - only users of ibmebus_request_irq()) and changes the way edge
interrupts are processed by the fasteoi handler.

  It works for the eHEA, dunno for the eHCA.

  So, unless all the designers of the XICS  eHEA have been shot to keep it
a secret, could someone knowledgeable shed some light on this issue.

  Thanks,

  Sebastien.

Not-Signed-off-by: Sebastien Dugue [EMAIL PROTECTED]
---
 arch/powerpc/kernel/ibmebus.c |   11 ++-
 kernel/irq/chip.c |5 +++--
 kernel/irq/manage.c   |9 ++---
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 9971159..5200323 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
 #include linux/kobject.h
 #include linux/dma-mapping.h
 #include linux/interrupt.h
+#include linux/irq.h
 #include linux/of.h
 #include linux/of_platform.h
 #include asm/ibmebus.h
@@ -213,11 +214,19 @@ int ibmebus_request_irq(u32 ist, irq_handler_t handler,
void *dev_id)
 {
unsigned int irq = irq_create_mapping(NULL, ist);
+   struct irq_desc *desc;
+   int ret;
 
 	if (irq == NO_IRQ)

return -EINVAL;
 
-	return request_irq(irq, handler, irq_flags, devname, dev_id);

+   ret = request_irq(irq, handler, irq_flags, devname, dev_id);
+
+   desc = irq_desc + irq;
+   desc-status = ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+   desc-status |= IRQ_TYPE_EDGE_RISING;
+
+   return ret;
 }
 EXPORT_SYMBOL(ibmebus_request_irq);
 
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c

index b7b397a..6d366ca 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -430,7 +430,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
action = desc-action;
if (unlikely(!action || (desc-status  (IRQ_INPROGRESS |
 IRQ_DISABLED {
-   desc-status |= IRQ_PENDING;
+   desc-status |= IRQ_PENDING | IRQ_MASKED;
if (desc-chip-mask)
desc-chip-mask(irq);
goto out;
@@ -439,9 +439,10 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
desc-status |= IRQ_INPROGRESS;
/*
 * In the threaded case we fall back to a mask+eoi sequence:
+* excepted for edge interrupts which are not masked.
 */
if (redirect_hardirq(desc)) {
-   if (desc-chip-mask)
+   if (desc-chip-mask  !(desc-status  IRQ_TYPE_EDGE_BOTH))
desc-chip-mask(irq);
goto out;
}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 3bffa20..3e39c71 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -788,9 +788,12 @@ static void do_hardirq(struct irq_desc *desc)
thread_simple_irq(desc);
else if (desc-handle_irq == handle_level_irq)
thread_level_irq(desc);
-   else if (desc-handle_irq == handle_fasteoi_irq)
-   thread_fasteoi_irq(desc);
-   else if (desc-handle_irq == handle_edge_irq)
+   else 

Re: [PATCH 2/2] ehea: fix mutex and spinlock use

2008-09-15 Thread Thomas Klein

NACK!

I regret but this patch is wrong. It is not sufficient to only lock
the replacement of an old list with a new list. Building up those
lists is a 3-step process:

1. Count the number of entries a list will contain and allocate mem
2. Fill the list
3. Replace old list with updated list

It's obvious that the contents of the list may not change during this
procedure. That means that not only the list build-up procedure must
be locked. It must be assured that no function that modifies the list's
content can be called while another list update is in progress.

Jeff, please revert this patch.

Thanks
Thomas



Sebastien Dugue wrote:

  Looks like to me that the ehea_fw_handles.lock mutex and the
ehea_bcmc_regs.lock spinlock are taken much longer than necessary and could
as well be pushed inside the functions that need them
(ehea_update_firmware_handles() and ehea_update_bcmc_registrations())
rather than at each callsite.

Signed-off-by: Sebastien Dugue [EMAIL PROTECTED]
---
 drivers/net/ehea/ehea_main.c |   26 --
 1 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index b70c531..c765ec6 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -219,9 +219,11 @@ static void ehea_update_firmware_handles(void)
}
 
 out_update:

+   mutex_lock(ehea_fw_handles.lock);
kfree(ehea_fw_handles.arr);
ehea_fw_handles.arr = arr;
ehea_fw_handles.num_entries = i;
+   mutex_unlock(ehea_fw_handles.lock);
 }
 
 static void ehea_update_bcmc_registrations(void)

@@ -293,9 +295,11 @@ static void ehea_update_bcmc_registrations(void)
}
 
 out_update:

+   spin_lock(ehea_bcmc_regs.lock);
kfree(ehea_bcmc_regs.arr);
ehea_bcmc_regs.arr = arr;
ehea_bcmc_regs.num_entries = i;
+   spin_unlock(ehea_bcmc_regs.lock);
 }
 
 static struct net_device_stats *ehea_get_stats(struct net_device *dev)

@@ -1770,8 +1774,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void 
*sa)
 
 	memcpy(dev-dev_addr, mac_addr-sa_data, dev-addr_len);
 
-	spin_lock(ehea_bcmc_regs.lock);

-
/* Deregister old MAC in pHYP */
if (port-state == EHEA_PORT_UP) {
ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
@@ -1792,7 +1794,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void 
*sa)
 
 out_upregs:

ehea_update_bcmc_registrations();
-   spin_unlock(ehea_bcmc_regs.lock);
 out_free:
kfree(cb0);
 out:
@@ -1954,8 +1955,6 @@ static void ehea_set_multicast_list(struct net_device 
*dev)
}
ehea_promiscuous(dev, 0);
 
-	spin_lock(ehea_bcmc_regs.lock);

-
if (dev-flags  IFF_ALLMULTI) {
ehea_allmulti(dev, 1);
goto out;
@@ -1985,7 +1984,6 @@ static void ehea_set_multicast_list(struct net_device 
*dev)
}
 out:
ehea_update_bcmc_registrations();
-   spin_unlock(ehea_bcmc_regs.lock);
return;
 }
 
@@ -2466,8 +2464,6 @@ static int ehea_up(struct net_device *dev)

if (port-state == EHEA_PORT_UP)
return 0;
 
-	mutex_lock(ehea_fw_handles.lock);

-
ret = ehea_port_res_setup(port, port-num_def_qps,
  port-num_add_tx_qps);
if (ret) {
@@ -2504,8 +2500,6 @@ static int ehea_up(struct net_device *dev)
}
}
 
-	spin_lock(ehea_bcmc_regs.lock);

-
ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
if (ret) {
ret = -EIO;
@@ -2527,10 +2521,8 @@ out:
ehea_info(Failed starting %s. ret=%i, dev-name, ret);
 
 	ehea_update_bcmc_registrations();

-   spin_unlock(ehea_bcmc_regs.lock);
 
 	ehea_update_firmware_handles();

-   mutex_unlock(ehea_fw_handles.lock);
 
 	return ret;

 }
@@ -2580,9 +2572,6 @@ static int ehea_down(struct net_device *dev)
if (port-state == EHEA_PORT_DOWN)
return 0;
 
-	mutex_lock(ehea_fw_handles.lock);

-
-   spin_lock(ehea_bcmc_regs.lock);
ehea_drop_multicast_list(dev);
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
@@ -2591,7 +2580,6 @@ static int ehea_down(struct net_device *dev)

port-state = EHEA_PORT_DOWN;
 
 	ehea_update_bcmc_registrations();

-   spin_unlock(ehea_bcmc_regs.lock);
 
 	ret = ehea_clean_all_portres(port);

if (ret)
@@ -2599,7 +2587,6 @@ static int ehea_down(struct net_device *dev)
  dev-name, ret);
 
 	ehea_update_firmware_handles();

-   mutex_unlock(ehea_fw_handles.lock);
 
 	return ret;

 }
@@ -3378,7 +3365,6 @@ static int __devinit ehea_probe_adapter(struct of_device 
*dev,
ehea_error(Invalid ibmebus device probed);
return -EINVAL;
}
-   mutex_lock(ehea_fw_handles.lock);
 
 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);

if (!adapter) {
@@ -3462,7 +3448,6 @@ out_free_ad:
 
 out:


[PATCH] ehea: Fix DLPAR memory add support

2008-04-04 Thread Thomas Klein
This patch fixes two weaknesses in send/receive packet handling which may
lead to kernel panics during DLPAR memory add operations.

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp -X dontdiff linux-2.6.25-rc8/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.25-rc8/drivers/net/ehea/ehea.h2008-04-01 21:44:26.0 
+0200
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-04-03 15:36:36.0 
+0200
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0089
+#define DRV_VERSIONEHEA_0090
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -371,6 +371,7 @@ struct ehea_port_res {
struct ehea_q_skb_arr rq2_skba;
struct ehea_q_skb_arr rq3_skba;
struct ehea_q_skb_arr sq_skba;
+   int sq_skba_size;
spinlock_t netif_queue;
int queue_stopped;
int swqe_refill_th;
diff -Nurp -X dontdiff linux-2.6.25-rc8/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.25-rc8/drivers/net/ehea/ehea_main.c   2008-04-01 
21:44:26.0 +0200
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-04-03 15:36:36.0 
+0200
@@ -349,7 +349,8 @@ static void ehea_refill_rq1(struct ehea_
pr-rq1_skba.os_skbs = 0;
 
if (unlikely(test_bit(__EHEA_STOP_XFER, ehea_driver_flags))) {
-   pr-rq1_skba.index = index;
+   if (nr_of_wqes  0)
+   pr-rq1_skba.index = index;
pr-rq1_skba.os_skbs = fill_wqes;
return;
}
@@ -1464,7 +1465,9 @@ static int ehea_init_port_res(struct ehe
  init_attr-act_nr_rwqes_rq2,
  init_attr-act_nr_rwqes_rq3);
 
-   ret = ehea_init_q_skba(pr-sq_skba, init_attr-act_nr_send_wqes + 1);
+   pr-sq_skba_size = init_attr-act_nr_send_wqes + 1;
+
+   ret = ehea_init_q_skba(pr-sq_skba, pr-sq_skba_size);
ret |= ehea_init_q_skba(pr-rq1_skba, init_attr-act_nr_rwqes_rq1 + 1);
ret |= ehea_init_q_skba(pr-rq2_skba, init_attr-act_nr_rwqes_rq2 + 1);
ret |= ehea_init_q_skba(pr-rq3_skba, init_attr-act_nr_rwqes_rq3 + 1);
@@ -2621,6 +2624,22 @@ void ehea_purge_sq(struct ehea_qp *orig_
}
 }
 
+void ehea_flush_sq(struct ehea_port *port)
+{
+   int i;
+
+   for (i = 0; i  port-num_def_qps + port-num_add_tx_qps; i++) {
+   struct ehea_port_res *pr = port-port_res[i];
+   int swqe_max = pr-sq_skba_size - 2 - pr-swqe_ll_count;
+   int k = 0;
+   while (atomic_read(pr-swqe_avail)  swqe_max) {
+   msleep(5);
+   if (++k == 20)
+   break;
+   }
+   }
+}
+
 int ehea_stop_qps(struct net_device *dev)
 {
struct ehea_port *port = netdev_priv(dev);
@@ -2845,6 +2864,7 @@ static void ehea_rereg_mrs(struct work_s
if (dev-flags  IFF_UP) {
down(port-port_lock);
netif_stop_queue(dev);
+   ehea_flush_sq(port);
ret = ehea_stop_qps(dev);
if (ret) {
up(port-port_lock);
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] ehea: Fix IPv6 support

2008-03-25 Thread Thomas Klein
Andrew Morton wrote:
 On Wed, 19 Mar 2008 13:55:43 +0100
 Thomas Klein [EMAIL PROTECTED] wrote:
 
 Indicate that HEA calculates IPv4 checksums only

 Signed-off-by: Thomas Klein [EMAIL PROTECTED]

 ---
 diff -Nurp -X dontdiff linux-2.6.25-rc6/drivers/net/ehea/ehea.h 
 patched_kernel/drivers/net/ehea/ehea.h
 --- linux-2.6.25-rc6/drivers/net/ehea/ehea.h 2008-03-17 00:32:14.0 
 +0100
 +++ patched_kernel/drivers/net/ehea/ehea.h   2008-03-19 08:58:07.0 
 +0100
 @@ -40,7 +40,7 @@
  #include asm/io.h
  
  #define DRV_NAMEehea
 -#define DRV_VERSION EHEA_0087
 +#define DRV_VERSION EHEA_0089
  
  /* eHEA capability flags */
  #define DLPAR_PORT_ADD_REM 1
 diff -Nurp -X dontdiff linux-2.6.25-rc6/drivers/net/ehea/ehea_main.c 
 patched_kernel/drivers/net/ehea/ehea_main.c
 --- linux-2.6.25-rc6/drivers/net/ehea/ehea_main.c2008-03-17 
 00:32:14.0 +0100
 +++ patched_kernel/drivers/net/ehea/ehea_main.c  2008-03-19 
 08:58:07.0 +0100
 @@ -3108,7 +3108,7 @@ struct ehea_port *ehea_setup_single_port
  dev-vlan_rx_add_vid = ehea_vlan_rx_add_vid;
  dev-vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
  dev-features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
 -  | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
 +  | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
| NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
| NETIF_F_LLTX;
  dev-tx_timeout = ehea_tx_watchdog;
 
 That looks like a pretty significant fix to me?  Should it be backported to
 2.6.24.x?

Agreed. I'll send a patch.

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


[PATCH 2.6.24-stable] ehea: Fix IPv6 support

2008-03-25 Thread Thomas Klein
Indicate that HEA calculates IPv4 checksums only

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp linux-2.6.24.4.org/drivers/net/ehea/ehea.h 
linux-2.6.24.4/drivers/net/ehea/ehea.h
--- linux-2.6.24.4.org/drivers/net/ehea/ehea.h  2008-03-25 12:42:18.0 
+0100
+++ linux-2.6.24.4/drivers/net/ehea/ehea.h  2008-03-25 13:13:29.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0083
+#define DRV_VERSIONEHEA_0083a
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp linux-2.6.24.4.org/drivers/net/ehea/ehea_main.c 
linux-2.6.24.4/drivers/net/ehea/ehea_main.c
--- linux-2.6.24.4.org/drivers/net/ehea/ehea_main.c 2008-03-25 
12:42:18.0 +0100
+++ linux-2.6.24.4/drivers/net/ehea/ehea_main.c 2008-03-25 13:13:12.0 
+0100
@@ -2945,7 +2945,7 @@ struct ehea_port *ehea_setup_single_port
dev-vlan_rx_add_vid = ehea_vlan_rx_add_vid;
dev-vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
dev-features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
- | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
+ | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
  | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
  | NETIF_F_LLTX;
dev-tx_timeout = ehea_tx_watchdog;
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ehea: Fix IPv6 support

2008-03-19 Thread Thomas Klein
Indicate that HEA calculates IPv4 checksums only

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp -X dontdiff linux-2.6.25-rc6/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.25-rc6/drivers/net/ehea/ehea.h2008-03-17 00:32:14.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2008-03-19 08:58:07.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0087
+#define DRV_VERSIONEHEA_0089
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff -Nurp -X dontdiff linux-2.6.25-rc6/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.25-rc6/drivers/net/ehea/ehea_main.c   2008-03-17 
00:32:14.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2008-03-19 08:58:07.0 
+0100
@@ -3108,7 +3108,7 @@ struct ehea_port *ehea_setup_single_port
dev-vlan_rx_add_vid = ehea_vlan_rx_add_vid;
dev-vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
dev-features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
- | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
+ | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
  | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
  | NETIF_F_LLTX;
dev-tx_timeout = ehea_tx_watchdog;
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ehea: Fix missing Kconfig dependency

2008-03-03 Thread Thomas Klein
Fixed Kconfig: ehea driver requires sparse mem

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp linux-2.6.25-rc3.org/drivers/net/Kconfig 
linux-2.6.25-rc3/drivers/net/Kconfig
--- linux-2.6.25-rc3.org/drivers/net/Kconfig2008-02-24 22:25:54.0 
+0100
+++ linux-2.6.25-rc3/drivers/net/Kconfig2008-03-03 13:36:48.0 
+0100
@@ -2513,7 +2513,7 @@ config CHELSIO_T3
 
 config EHEA
tristate eHEA Ethernet support
-   depends on IBMEBUS  INET
+   depends on IBMEBUS  INET  SPARSEMEM
select INET_LRO
---help---
  This driver supports the IBM pSeries eHEA ethernet adapter.
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ehea: add kdump support

2008-02-13 Thread Thomas Klein
This patch adds kdump support to the ehea driver. As the firmware doesn't free
resource handles automatically, the driver has to run an as simple as possible
free resource function in case of a crash shutdown. The function iterates over
two arrays freeing all resource handles which are stored there. The arrays are
kept up-to-date during normal runtime. The crash handler fn is triggered by the
recently introduced PPC crash shutdown reg/unreg functions.


Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
 drivers/net/ehea/ehea.h  |   34 +-
 drivers/net/ehea/ehea_main.c |  281 ++
 2 files changed, 290 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 88fb53e..7c4ead3 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
 #include asm/io.h

 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0083
+#define DRV_VERSIONEHEA_0087

 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -386,6 +386,13 @@ struct ehea_port_res {


 #define EHEA_MAX_PORTS 16
+
+#define EHEA_NUM_PORTRES_FW_HANDLES6  /* QP handle, SendCQ handle,
+RecvCQ handle, EQ handle,
+SendMR handle, RecvMR handle */
+#define EHEA_NUM_PORT_FW_HANDLES   1  /* EQ handle */
+#define EHEA_NUM_ADAPTER_FW_HANDLES2  /* MR handle, NEQ handle */
+
 struct ehea_adapter {
u64 handle;
struct of_device *ofdev;
@@ -405,6 +412,31 @@ struct ehea_mc_list {
u64 macaddr;
 };

+/* kdump support */
+struct ehea_fw_handle_entry {
+   u64 adh;   /* Adapter Handle */
+   u64 fwh;   /* Firmware Handle */
+};
+
+struct ehea_fw_handle_array {
+   struct ehea_fw_handle_entry *arr;
+   int num_entries;
+   struct semaphore lock;
+};
+
+struct ehea_bcmc_reg_entry {
+   u64 adh;   /* Adapter Handle */
+   u32 port_id;   /* Logical Port Id */
+   u8 reg_type;   /* Registration Type */
+   u64 macaddr;
+};
+
+struct ehea_bcmc_reg_array {
+   struct ehea_bcmc_reg_entry *arr;
+   int num_entries;
+   struct semaphore lock;
+};
+
 #define EHEA_PORT_UP 1
 #define EHEA_PORT_DOWN 0
 #define EHEA_PHY_LINK_UP 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index c051c7e..21af674 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -35,6 +35,7 @@
 #include linux/if_ether.h
 #include linux/notifier.h
 #include linux/reboot.h
+#include asm/kexec.h

 #include net/ip.h

@@ -98,8 +99,10 @@ static int port_name_cnt;
 static LIST_HEAD(adapter_list);
 u64 ehea_driver_flags;
 struct work_struct ehea_rereg_mr_task;
-
 struct semaphore dlpar_mem_lock;
+struct ehea_fw_handle_array ehea_fw_handles;
+struct ehea_bcmc_reg_array ehea_bcmc_regs;
+

 static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id);
@@ -132,6 +135,160 @@ void ehea_dump(void *adr, int len, char *msg)
}
 }

+static void ehea_update_firmware_handles(void)
+{
+   struct ehea_fw_handle_entry *arr = NULL;
+   struct ehea_adapter *adapter;
+   int num_adapters = 0;
+   int num_ports = 0;
+   int num_portres = 0;
+   int i = 0;
+   int num_fw_handles, k, l;
+
+   /* Determine number of handles */
+   list_for_each_entry(adapter, adapter_list, list) {
+   num_adapters++;
+
+   for (k = 0; k  EHEA_MAX_PORTS; k++) {
+   struct ehea_port *port = adapter-port[k];
+
+   if (!port || (port-state != EHEA_PORT_UP))
+   continue;
+
+   num_ports++;
+   num_portres += port-num_def_qps + port-num_add_tx_qps;
+   }
+   }
+
+   num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES +
+num_ports * EHEA_NUM_PORT_FW_HANDLES +
+num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
+
+   if (num_fw_handles) {
+   arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
+   if (!arr)
+   return;  /* Keep the existing array */
+   } else
+   goto out_update;
+
+   list_for_each_entry(adapter, adapter_list, list) {
+   for (k = 0; k  EHEA_MAX_PORTS; k++) {
+   struct ehea_port *port = adapter-port[k];
+
+   if (!port || (port-state != EHEA_PORT_UP))
+   continue;
+
+   for (l = 0;
+l  port-num_def_qps + port-num_add_tx_qps;
+l++) {
+   struct ehea_port_res *pr = port-port_res[l];
+
+   arr[i].adh = adapter-handle;
+   arr[i++].fwh

[RFC] ehea: kdump support - rework

2007-12-17 Thread Thomas Klein
This patch adds kdump support using the new PPC crash shutdown hook to the
ehea driver.
The reworked implementation follows the feedback I got. The crash handler
now just iterates over two simple arrays instead of handling linked lists.

Further feedback will be appreciated.

ehea kdump support RFC #1:
  http://lkml.org/lkml/2007/12/12/241


Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.24-rc5/drivers/net/ehea/ehea.h2007-12-11 04:48:43.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2007-12-17 16:18:49.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0083
+#define DRV_VERSIONEHEA_0085
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -386,6 +386,13 @@ struct ehea_port_res {
 
 
 #define EHEA_MAX_PORTS 16
+
+#define EHEA_NUM_PORTRES_FW_HANDLES6  /* QP handle, SendCQ handle,
+RecvCQ handle, EQ handle,
+SendMR handle, RecvMR handle */
+#define EHEA_NUM_PORT_FW_HANDLES   1  /* EQ handle */
+#define EHEA_NUM_ADAPTER_FW_HANDLES2  /* MR handle, NEQ handle */
+
 struct ehea_adapter {
u64 handle;
struct of_device *ofdev;
@@ -405,6 +412,31 @@ struct ehea_mc_list {
u64 macaddr;
 };
 
+/* kdump support */
+struct ehea_fw_handle_entry {
+   u64 adh;   /* Adapter Handle */
+   u64 fwh;   /* Firmware Handle */
+};
+
+struct ehea_fw_handle_array {
+   struct ehea_fw_handle_entry *arr;
+   int num_entries;
+   struct semaphore lock;
+};
+
+struct ehea_bcmc_reg_entry {
+   u64 adh;   /* Adapter Handle */
+   u32 port_id;   /* Logical Port Id */
+   u8 reg_type;   /* Registration Type */
+   u64 macaddr;
+};
+
+struct ehea_bcmc_reg_array {
+   struct ehea_bcmc_reg_entry *arr;
+   int num_entries;
+   struct semaphore lock;
+};
+
 #define EHEA_PORT_UP 1
 #define EHEA_PORT_DOWN 0
 #define EHEA_PHY_LINK_UP 1
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c   2007-12-11 
04:48:43.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2007-12-17 16:18:49.0 
+0100
@@ -35,6 +35,7 @@
 #include linux/if_ether.h
 #include linux/notifier.h
 #include linux/reboot.h
+#include asm/kexec.h
 
 #include net/ip.h
 
@@ -98,8 +99,10 @@ static int port_name_cnt = 0;
 static LIST_HEAD(adapter_list);
 u64 ehea_driver_flags = 0;
 struct work_struct ehea_rereg_mr_task;
-
 struct semaphore dlpar_mem_lock;
+struct ehea_fw_handle_array ehea_fw_handles;
+struct ehea_bcmc_reg_array ehea_bcmc_regs;
+
 
 static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id);
@@ -131,6 +134,160 @@ void ehea_dump(void *adr, int len, char 
}
 }
 
+static void ehea_update_firmware_handles(void)
+{
+   struct ehea_fw_handle_entry *arr = NULL;
+   struct ehea_adapter *adapter;
+   int num_adapters = 0;
+   int num_ports = 0;
+   int num_portres = 0;
+   int i = 0;
+   int num_fw_handles, k, l;
+
+   /* Determine number of handles */
+   list_for_each_entry(adapter, adapter_list, list) {
+   num_adapters++;
+
+   for (k = 0; k  EHEA_MAX_PORTS; k++) {
+   struct ehea_port *port = adapter-port[k];
+
+   if (!port || (port-state != EHEA_PORT_UP))
+   continue;
+
+   num_ports++;
+   num_portres += port-num_def_qps + port-num_add_tx_qps;
+   }
+   }
+
+   num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES +
+num_ports * EHEA_NUM_PORT_FW_HANDLES +
+num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
+
+   if (num_fw_handles) {
+   arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
+   if (!arr)
+   return;  /* Keep the existing array */
+   } else
+   goto out_update;
+
+   list_for_each_entry(adapter, adapter_list, list) {
+   for (k = 0; k  EHEA_MAX_PORTS; k++) {
+   struct ehea_port *port = adapter-port[k];
+
+   if (!port || (port-state != EHEA_PORT_UP))
+   continue;
+
+   for (l = 0;
+l  port-num_def_qps + port-num_add_tx_qps;
+l++) {
+   struct ehea_port_res *pr = port-port_res[l];
+
+   arr[i].adh = adapter-handle;
+   arr[i++].fwh = pr-qp-fw_handle

[RFC] ehea: kdump support using new shutdown hook

2007-12-12 Thread Thomas Klein
This patch adds kdump support using the new PPC crash shutdown hook to the
ehea driver. The driver now keeps a list of firmware handles which have to
be freed in case of a crash. The crash handler does the minimum required: it
frees the firmware resource handles plus broadcast/multicast registrations.

Please comment.

Shutdown hook patches:
  http://ozlabs.org/pipermail/linuxppc-dev/2007-December/048058.html
  http://ozlabs.org/pipermail/linuxppc-dev/2007-December/048059.html


Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea.h 
patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.24-rc5/drivers/net/ehea/ehea.h2007-12-11 04:48:43.0 
+0100
+++ patched_kernel/drivers/net/ehea/ehea.h  2007-12-12 17:30:53.0 
+0100
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0083
+#define DRV_VERSIONEHEA_0084
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -386,6 +386,7 @@ struct ehea_port_res {
 
 
 #define EHEA_MAX_PORTS 16
+#define EHEA_MAX_RES_HANDLES (100 * EHEA_MAX_PORTS + 10)
 struct ehea_adapter {
u64 handle;
struct of_device *ofdev;
@@ -397,6 +398,7 @@ struct ehea_adapter {
u64 max_mc_mac;/* max number of multicast mac addresses */
int active_ports;
struct list_head list;
+   u64 res_handles[EHEA_MAX_RES_HANDLES];
 };
 
 
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c 
patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c   2007-12-11 
04:48:43.0 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2007-12-12 17:30:53.0 
+0100
@@ -35,6 +35,7 @@
 #include linux/if_ether.h
 #include linux/notifier.h
 #include linux/reboot.h
+#include asm-powerpc/kexec.h
 
 #include net/ip.h
 
@@ -2256,6 +2257,33 @@ static int ehea_clean_all_portres(struct
return ret;
 }
 
+static void ehea_update_adapter_handles(struct ehea_adapter *adapter)
+{
+   int i, k;
+   int j = 0;
+
+   memset(adapter-res_handles, sizeof(adapter-res_handles), 0);
+
+   for (k = 0; k  EHEA_MAX_PORTS; k++) {
+   struct ehea_port *port = adapter-port[k];
+
+   if (!port || (port-state != EHEA_PORT_UP))
+   continue;
+
+   for(i = 0; i  port-num_def_qps + port-num_add_tx_qps; i++) {
+   struct ehea_port_res *pr = port-port_res[i];
+
+   adapter-res_handles[j++] = pr-qp-fw_handle;
+   adapter-res_handles[j++] = pr-send_cq-fw_handle;
+   adapter-res_handles[j++] = pr-recv_cq-fw_handle;
+   adapter-res_handles[j++] = pr-eq-fw_handle;
+   adapter-res_handles[j++] = pr-send_mr.handle;
+   adapter-res_handles[j++] = pr-recv_mr.handle;
+   }
+   adapter-res_handles[j++] = port-qp_eq-fw_handle;
+   }
+}
+
 static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
 {
if (adapter-active_ports)
@@ -2318,6 +2346,7 @@ static int ehea_up(struct net_device *de
 
ret = 0;
port-state = EHEA_PORT_UP;
+   ehea_update_adapter_handles(port-adapter);
goto out;
 
 out_free_irqs:
@@ -2387,6 +2416,8 @@ static int ehea_down(struct net_device *
ehea_info(Failed freeing resources for %s. ret=%i,
  dev-name, ret);
 
+   ehea_update_adapter_handles(port-adapter);
+
return ret;
 }
 
@@ -3302,6 +,71 @@ static int __devexit ehea_remove(struct 
return 0;
 }
 
+void ehea_crash_deregister(void)
+{
+   struct ehea_adapter *adapter;
+   int i;
+   u64 hret;
+   u8 reg_type;
+
+   list_for_each_entry(adapter, adapter_list, list) {
+   for (i = 0; i  EHEA_MAX_PORTS; i++) {
+   struct ehea_port *port = adapter-port[i];
+   if (port-state == EHEA_PORT_UP) {
+   struct ehea_mc_list *mc_entry = port-mc_list;
+   struct list_head *pos;
+   struct list_head *temp;
+
+   /* Undo multicast registrations */
+   list_for_each_safe(pos, temp,
+  (port-mc_list-list)) {
+   mc_entry = list_entry(pos,
+   struct ehea_mc_list,
+   list);
+   ehea_multicast_reg_helper(port,
+ mc_entry-macaddr,
+ H_DEREG_BCMC);
+   }
+
+   /* Undo broad registration

[PATCH] ehea: Add kdump support

2007-11-09 Thread Thomas Klein
To support ehea driver reloading in a kdump kernel the driver has to perform
firmware handle deregistrations when the original kernel crashes. As there's
currently no notifier chain for machine crashes this patch enables kdump support
in the ehea driver by bending the ppc_md.machine_crash_shutdown hook to its own
machine crash handler. The original machine_crash_shutdown() fn is called
afterwards. This works fine as long as the ehea driver is the only one which
does so. Problems may occur if other drivers do the same and unload regularly.
This patch enables 2.6.24-rc2 to use kdump with ehea and only puts a very
low risk on base kernel. In 2.6.24 we know ehea is the only user of this
mechanism. The next step for 2.6.25 would be to add a proper notifier chain.
The full solution might be that register_reboot_notifier() provides sth
like a SYS_CRASH action. Please apply.

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
 drivers/net/ehea/ehea.h  |2 +-
 drivers/net/ehea/ehea_main.c |   28 
 2 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index f78e5bf..5935899 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0080
+#define DRV_VERSIONEHEA_0081
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index f0319f1..40a732e 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -37,6 +37,7 @@
 #include linux/reboot.h
 
 #include net/ip.h
+#include asm-powerpc/machdep.h
 
 #include ehea.h
 #include ehea_qmr.h
@@ -98,6 +99,7 @@ static int port_name_cnt = 0;
 static LIST_HEAD(adapter_list);
 u64 ehea_driver_flags = 0;
 struct work_struct ehea_rereg_mr_task;
+static void (*orig_machine_crash_shutdown)(struct pt_regs *regs);
 
 struct semaphore dlpar_mem_lock;
 
@@ -3312,6 +3314,29 @@ static struct notifier_block ehea_reboot_nb = {
 .notifier_call = ehea_reboot_notifier,
 };
 
+void ehea_crash_notifier(struct pt_regs *regs)
+{
+   ehea_info(Machine crash: freeing all eHEA resources);
+   ibmebus_unregister_driver(ehea_driver);
+   orig_machine_crash_shutdown(regs);
+}
+
+void ehea_register_crash_notifier(void)
+{
+#ifdef CONFIG_KEXEC
+   orig_machine_crash_shutdown =
+   (void*)__xchg_u64((unsigned 
long*)ppc_md.machine_crash_shutdown,
+(unsigned long)ehea_crash_notifier);
+#endif
+}
+
+void ehea_unregister_crash_notifier(void)
+{
+#ifdef CONFIG_KEXEC
+   ppc_md.machine_crash_shutdown = orig_machine_crash_shutdown;
+#endif
+}
+
 static int check_module_parm(void)
 {
int ret = 0;
@@ -3369,6 +3394,7 @@ int __init ehea_module_init(void)
goto out;
 
register_reboot_notifier(ehea_reboot_nb);
+   ehea_register_crash_notifier();
 
ret = ibmebus_register_driver(ehea_driver);
if (ret) {
@@ -3382,6 +3408,7 @@ int __init ehea_module_init(void)
ehea_error(failed to register capabilities attribute, ret=%d,
   ret);
unregister_reboot_notifier(ehea_reboot_nb);
+   ehea_unregister_crash_notifier();
ibmebus_unregister_driver(ehea_driver);
goto out;
}
@@ -3396,6 +3423,7 @@ static void __exit ehea_module_exit(void)
driver_remove_file(ehea_driver.driver, driver_attr_capabilities);
ibmebus_unregister_driver(ehea_driver);
unregister_reboot_notifier(ehea_reboot_nb);
+   ehea_unregister_crash_notifier();
ehea_destroy_busmap();
 }
 
-- 
1.5.2
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[RESEND][PATCH 2/3] ehea: Simplify resource usage check

2007-08-06 Thread Thomas Klein
Use shorter method to determine whether adapter has configured ports

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
 drivers/net/ehea/ehea_main.c |   18 ++
 1 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index d43ab0f..36ca322 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -2165,24 +2165,18 @@ static int ehea_clean_all_portres(struct ehea_port 
*port)
return ret;
 }
 
-static void ehea_remove_adapter_mr (struct ehea_adapter *adapter)
+static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
 {
-   int i;
-
-   for (i=0; i  EHEA_MAX_PORTS; i++)
-   if (adapter-port[i])
-   return;
+   if (adapter-active_ports)
+   return;
 
ehea_rem_mr(adapter-mr);
 }
 
-static int ehea_add_adapter_mr (struct ehea_adapter *adapter)
+static int ehea_add_adapter_mr(struct ehea_adapter *adapter)
 {
-   int i;
-
-   for (i=0; i  EHEA_MAX_PORTS; i++)
-   if (adapter-port[i])
-   return 0;
+   if (adapter-active_ports)
+   return 0;
 
return ehea_reg_kernel_mr(adapter, adapter-mr);
 }
-- 
1.5.2



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


[RESEND][PATCH 3/3] ehea: Eliminated some compiler warnings

2007-08-06 Thread Thomas Klein
Fixed wrongly casted pointers

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
 drivers/net/ehea/ehea_main.c |   25 ++---
 1 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 36ca322..9756211 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -1326,7 +1326,6 @@ static void write_swqe2_TSO(struct sk_buff *skb,
u8 *imm_data = swqe-u.immdata_desc.immediate_data[0];
int skb_data_size = skb-len - skb-data_len;
int headersize;
-   u64 tmp_addr;
 
/* Packet is TCP with TSO enabled */
swqe-tx_control |= EHEA_SWQE_TSO;
@@ -1347,9 +1346,8 @@ static void write_swqe2_TSO(struct sk_buff *skb,
/* set sg1entry data */
sg1entry-l_key = lkey;
sg1entry-len = skb_data_size - headersize;
-
-   tmp_addr = (u64)(skb-data + headersize);
-   sg1entry-vaddr = ehea_map_vaddr(tmp_addr);
+   sg1entry-vaddr =
+   ehea_map_vaddr(skb-data + headersize);
swqe-descriptors++;
}
} else
@@ -1362,7 +1360,6 @@ static void write_swqe2_nonTSO(struct sk_buff *skb,
int skb_data_size = skb-len - skb-data_len;
u8 *imm_data = swqe-u.immdata_desc.immediate_data[0];
struct ehea_vsgentry *sg1entry = swqe-u.immdata_desc.sg_entry;
-   u64 tmp_addr;
 
/* Packet is any nonTSO type
 *
@@ -1379,8 +1376,8 @@ static void write_swqe2_nonTSO(struct sk_buff *skb,
/* copy sg1entry data */
sg1entry-l_key = lkey;
sg1entry-len = skb_data_size - SWQE2_MAX_IMM;
-   tmp_addr = (u64)(skb-data + SWQE2_MAX_IMM);
-   sg1entry-vaddr = ehea_map_vaddr(tmp_addr);
+   sg1entry-vaddr =
+   ehea_map_vaddr(skb-data + SWQE2_MAX_IMM);
swqe-descriptors++;
}
} else {
@@ -1395,7 +1392,6 @@ static inline void write_swqe2_data(struct sk_buff *skb, 
struct net_device *dev,
struct ehea_vsgentry *sg_list, *sg1entry, *sgentry;
skb_frag_t *frag;
int nfrags, sg1entry_contains_frag_data, i;
-   u64 tmp_addr;
 
nfrags = skb_shinfo(skb)-nr_frags;
sg1entry = swqe-u.immdata_desc.sg_entry;
@@ -1417,9 +1413,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, 
struct net_device *dev,
/* copy sg1entry data */
sg1entry-l_key = lkey;
sg1entry-len = frag-size;
-   tmp_addr =  (u64)(page_address(frag-page)
- + frag-page_offset);
-   sg1entry-vaddr = ehea_map_vaddr(tmp_addr);
+   sg1entry-vaddr =
+   ehea_map_vaddr(page_address(frag-page)
+  + frag-page_offset);
swqe-descriptors++;
sg1entry_contains_frag_data = 1;
}
@@ -1431,10 +1427,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, 
struct net_device *dev,
 
sgentry-l_key = lkey;
sgentry-len = frag-size;
-
-   tmp_addr = (u64)(page_address(frag-page)
-+ frag-page_offset);
-   sgentry-vaddr = ehea_map_vaddr(tmp_addr);
+   sgentry-vaddr =
+   ehea_map_vaddr(page_address(frag-page)
+  + frag-page_offset);
swqe-descriptors++;
}
}
-- 
1.5.2


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


[PATCH 1/3] ehea: Fix workqueue handling

2007-07-30 Thread Thomas Klein
Fix: Workqueue ehea_driver_wq was not destroyed

Signed-off-by: Thomas Klein [EMAIL PROTECTED]

---
 drivers/net/ehea/ehea.h  |2 +-
 drivers/net/ehea/ehea_main.c |1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8ee2c2c..d67f97b 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
 #include asm/io.h
 
 #define DRV_NAME   ehea
-#define DRV_VERSIONEHEA_0072
+#define DRV_VERSIONEHEA_0073
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 58702f5..d43ab0f 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -3099,6 +3099,7 @@ out:
 
 static void __exit ehea_module_exit(void)
 {
+   destroy_workqueue(ehea_driver_wq);
driver_remove_file(ehea_driver.driver, driver_attr_capabilities);
ibmebus_unregister_driver(ehea_driver);
ehea_destroy_busmap();
-- 
1.5.2


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


Re: Possible eHEA performance issue

2007-07-20 Thread Thomas Klein
Michael Neuling wrote:
 From ehea_start_xmit in ehea_main.c we have:
 
 if (unlikely(atomic_read(pr-swqe_avail) = 1)) {
   spin_lock_irqsave(pr-netif_queue, flags);
   if (unlikely(atomic_read(pr-swqe_avail) = 1)) {
   pr-p_stats.queue_stopped++;
   netif_stop_queue(dev);
   pr-queue_stopped = 1;
   }
   spin_unlock_irqrestore(pr-netif_queue, flags);
 }
 
 Since the conditions are the same, isn't it likely that the second 'if'
 is going to be taken.  Hence, shouldn't the second 'unlikely' hint be
 removed or even changed to likely?
 
 Either way, some documentation here as to why it's done this way would
 be useful.  I assume the atomic_read is cheap compared to the
 spin_unlock_irqsave, so we quickly check swqe_avail before we check it
 again properly with the lock on so we can change some stuff.
 
 Mikey

Hi Mike,

good point the second if could be a likely(). The impact isn't that big
because the if statement is true in the unlikely() case that the send queue
is full - which doesn't happen often. Anyway we will modify this in one of
the next driver versions. Thanks for the hint!

Thomas

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