Re: [PATCH 1/2][RESEND] ehea: error handling improvement
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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