* [PATCH net-2.6 1/3] bnx2x: LSO code was broken on BE platforms
From: Vladislav Zolotarov @ 2010-12-12 14:11 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein
Make the LSO code work on BE platforms: parsing_data field of
a parsing BD (PBD) for 57712 was improperly composed which made FW read wrong
values for TCP header's length and offset and, as a result, the corresponding
PCI device was performing bad DMA reads triggering EEH.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x_cmn.c | 42 +++++++++++++++++++++++++---------------
1 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 94d5f59..0af361e 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -1782,15 +1782,15 @@ exit_lbl:
}
#endif
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
- struct eth_tx_parse_bd_e2 *pbd,
- u32 xmit_type)
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
+ u32 xmit_type)
{
- pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
- ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+ *parsing_data |= (skb_shinfo(skb)->gso_size <<
+ ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
+ ETH_TX_PARSE_BD_E2_LSO_MSS;
if ((xmit_type & XMIT_GSO_V6) &&
(ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
- pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+ *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
}
/**
@@ -1835,15 +1835,15 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
* @return header len
*/
static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
- struct eth_tx_parse_bd_e2 *pbd,
- u32 xmit_type)
+ u32 *parsing_data, u32 xmit_type)
{
- pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
- ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+ *parsing_data |= ((tcp_hdrlen(skb)/4) <<
+ ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+ ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
- pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
- skb->data) / 2) <<
- ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+ *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
+ ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+ ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
}
@@ -1912,6 +1912,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
+ u32 pbd_e2_parsing_data = 0;
u16 pkt_prod, bd_prod;
int nbd, fp_index;
dma_addr_t mapping;
@@ -2033,8 +2034,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
/* Set PBD in checksum offload case */
if (xmit_type & XMIT_CSUM)
- hlen = bnx2x_set_pbd_csum_e2(bp,
- skb, pbd_e2, xmit_type);
+ hlen = bnx2x_set_pbd_csum_e2(bp, skb,
+ &pbd_e2_parsing_data,
+ xmit_type);
} else {
pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
@@ -2076,10 +2078,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
hlen, bd_prod, ++nbd);
if (CHIP_IS_E2(bp))
- bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+ bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
+ xmit_type);
else
bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
}
+
+ /* Set the PBD's parsing_data field if not zero
+ * (for the chips newer than 57711).
+ */
+ if (pbd_e2_parsing_data)
+ pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data);
+
tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
/* Handle fragmented skb */
--
1.7.0.4
^ permalink raw reply related
* [PATCH 0/3 net-2.6] bnx2x: Backporting BE fixes from net-next
From: Vladislav Zolotarov @ 2010-12-12 14:11 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein, Ben Hutchings
Backporting the fix for a broken 57712 LSO code as for Ben's
suggestions. Also fixing the same compilation warning that has been
fixed in the net-next.
thanks,
vlad
^ permalink raw reply
* [PATCH net-2.6 2/3] bnx2x: Fixed a compilation warning
From: Vladislav Zolotarov @ 2010-12-12 14:12 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein
bnx2x_src_init_t2() is used only when BCM_CNIC is defined.
So, to avoid a compilation warning, we won't define it unless
BCM_CNIC is defined.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x_init_ops.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index a306b0e..66df29f 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -838,7 +838,7 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
/****************************************************************************
* SRC initializations
****************************************************************************/
-
+#ifdef BCM_CNIC
/* called during init func stage */
static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
dma_addr_t t2_mapping, int src_cid_count)
@@ -862,5 +862,5 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
U64_HI((u64)t2_mapping +
(src_cid_count-1) * sizeof(struct src_ent)));
}
-
+#endif
#endif /* BNX2X_INIT_OPS_H */
--
1.7.0.4
^ permalink raw reply related
* [PATCH net-2.6 3/3] bnx2x: Advance a version number to 1.60.01-0
From: Vladislav Zolotarov @ 2010-12-12 14:12 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 863e73a..dca1762 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -20,8 +20,8 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.60.00-4"
-#define DRV_MODULE_RELDATE "2010/11/01"
+#define DRV_MODULE_VERSION "1.60.01-0"
+#define DRV_MODULE_RELDATE "2010/11/12"
#define BNX2X_BC_VER 0x040200
#define BNX2X_MULTI_QUEUE
--
1.7.0.4
^ permalink raw reply related
* System blocks (hangs) on ifconfig up
From: Shmulik Hen @ 2010-12-12 15:00 UTC (permalink / raw)
To: netdev
Hello,
My system is Ubuntu 10.04, running kernel 2.6.32-26-generic.
Whenever I try to bring up a specific ethernet interface for the second
time, my
system becomes unresponsive for 60 seconds - i.e. no mouse, no keyboard, no
screen refresh. etc.
Looking at the driver's code, I could see that it's dev->open() method calls
wait_event_interruptible_timeout() with a timeout of 60 seconds - exactly
the delay I'm seeing.
I have narrowed the code to a bare minimum (see below - loosely based on
dummy.c), which only calls mdelay(10000) in it's dev->open() method, and
still, my system blocks for exactly 10 seconds when I run the following
sequence:
> sudo ifconfig shmulik0 up
> sudo ifconfig shmulik0 down
> sudo ifconfig shmulik0 up
At this point - the system is stuck for 10 seconds.
Thanks,
Shmulik.
------------------------------------------------------------------------------
shmulik.c:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
MODULE_AUTHOR("Shmulik Hen");
MODULE_DESCRIPTION("Shmulik's sample network driver");
MODULE_LICENSE("GPL");
static struct net_device *g_dev = NULL;
static int shmulik_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *sa = p;
if (!is_valid_ether_addr(sa->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
return 0;
}
static netdev_tx_t shmulik_start_xmit(struct sk_buff *skb, struct
net_device *dev)
{
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static int shmulik_open(struct net_device *dev)
{
mdelay(10000);
netif_carrier_on(dev);
netif_start_queue(dev);
return 0;
}
static int shmulik_close(struct net_device *dev)
{
netif_stop_queue(dev);
netif_carrier_off(dev);
return 0;
}
static const struct net_device_ops shmulik_drv_ops =
{
.ndo_open = shmulik_open,
.ndo_stop = shmulik_close,
.ndo_start_xmit = shmulik_start_xmit,
.ndo_set_mac_address = shmulik_set_mac_address,
};
static int __init shmulik_drv_init(void)
{
int rc;
struct net_device *dev;
if (g_dev)
return -EEXIST;
dev = alloc_etherdev(0);
if (!dev)
return -ENOMEM;
sprintf(dev->name, "%s%d" , "shmulik", 0);
dev->tx_queue_len = 0;
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
random_ether_addr(dev->dev_addr);
dev->netdev_ops = &shmulik_drv_ops;
rc = register_netdev(dev);
if (rc)
goto err_exit;
g_dev = dev;
return 0;
err_exit:
free_netdev(dev);
return rc;
}
static void __exit shmulik_drv_exit(void)
{
if (g_dev)
{
unregister_netdev(g_dev);
free_netdev(g_dev);
g_dev = NULL;
}
}
module_init(shmulik_drv_init);
module_exit(shmulik_drv_exit);
^ permalink raw reply
* System blocks (hangs) on ifconfig up
From: Shmulik Hen @ 2010-12-12 15:08 UTC (permalink / raw)
To: netdev
Hello,
My system is Ubuntu 10.04, running kernel 2.6.32-26-generic.
Whenever I try to bring up a specific ethernet interface for the second
time, my
system becomes unresponsive for 60 seconds - i.e. no mouse, no keyboard, no
screen refresh. etc.
Looking at the driver's code, I could see that it's dev->open() method
calls
wait_event_interruptible_timeout() with a timeout of 60 seconds - exactly
the delay I'm seeing.
I have narrowed the code to a bare minimum (see below - loosely based on
dummy.c), which only calls mdelay(10000) in it's dev->open() method, and
still, my system blocks for exactly 10 seconds when I run the following
sequence:
> sudo ifconfig shmulik0 up
> sudo ifconfig shmulik0 down
> sudo ifconfig shmulik0 up
At this point - the system is stuck for 10 seconds.
Thanks,
Shmulik.
------------------------------------------------------------------------------
shmulik.c:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
MODULE_AUTHOR("Shmulik Hen");
MODULE_DESCRIPTION("Shmulik's sample network driver");
MODULE_LICENSE("GPL");
static struct net_device *g_dev = NULL;
static int shmulik_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *sa = p;
if (!is_valid_ether_addr(sa->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
return 0;
}
static netdev_tx_t shmulik_start_xmit(struct sk_buff *skb, struct
net_device *dev)
{
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static int shmulik_open(struct net_device *dev)
{
mdelay(10000);
netif_carrier_on(dev);
netif_start_queue(dev);
return 0;
}
static int shmulik_close(struct net_device *dev)
{
netif_stop_queue(dev);
netif_carrier_off(dev);
return 0;
}
static const struct net_device_ops shmulik_drv_ops =
{
.ndo_open = shmulik_open,
.ndo_stop = shmulik_close,
.ndo_start_xmit = shmulik_start_xmit,
.ndo_set_mac_address = shmulik_set_mac_address,
};
static int __init shmulik_drv_init(void)
{
int rc;
struct net_device *dev;
if (g_dev)
return -EEXIST;
dev = alloc_etherdev(0);
if (!dev)
return -ENOMEM;
sprintf(dev->name, "%s%d" , "shmulik", 0);
dev->tx_queue_len = 0;
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
random_ether_addr(dev->dev_addr);
dev->netdev_ops = &shmulik_drv_ops;
rc = register_netdev(dev);
if (rc)
goto err_exit;
g_dev = dev;
return 0;
err_exit:
free_netdev(dev);
return rc;
}
static void __exit shmulik_drv_exit(void)
{
if (g_dev)
{
unregister_netdev(g_dev);
free_netdev(g_dev);
g_dev = NULL;
}
}
module_init(shmulik_drv_init);
module_exit(shmulik_drv_exit);
^ permalink raw reply
* Re: [PATCH net-next-2.6 v8 20/20] CAN : Replace netif_rx to netif_receive_skb
From: Marc Kleine-Budde @ 2010-12-12 15:15 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
qi.wang-ral2JQCrhuEAvxtiuMwx3w,
margie.foster-ral2JQCrhuEAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w,
joel.clark-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger
In-Reply-To: <4CFE16A3.6070903-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 1170 bytes --]
On 12/07/2010 12:12 PM, Tomoya MORINAGA wrote:
> Since this driver is implemented as NAPI,
> netif_receive_skb must be used not netif_rx.
>
> Signed-off-by: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Looks good.
Acked-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Marc
> ---
> drivers/net/can/pch_can.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 4697b1c..8d45fdd 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -572,7 +572,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)
> cf->data[7] = (errc & PCH_REC) >> 8;
>
> priv->can.state = state;
> - netif_rx(skb);
> + netif_receive_skb(skb);
>
> stats->rx_packets++;
> stats->rx_bytes += cf->can_dlc;
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: [PATCH net-next-2.6 v8 18/20] CAN : Optimize "if" condition in rx/tx processing
From: Marc Kleine-Budde @ 2010-12-12 15:16 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
qi.wang-ral2JQCrhuEAvxtiuMwx3w,
margie.foster-ral2JQCrhuEAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w,
joel.clark-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger
In-Reply-To: <4CFE166D.8040805-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 2720 bytes --]
On 12/07/2010 12:11 PM, Tomoya MORINAGA wrote:
> For reduce "if" condition, easy to read/understand the code,
> optimize "if" condition in rx/tx processing.
>
> Signed-off-by: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Acked-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
> drivers/net/can/pch_can.c | 26 ++++++++++----------------
> 1 files changed, 10 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 8efbe35..dcd8f00 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -746,19 +746,16 @@ static int pch_can_poll(struct napi_struct *napi, int quota)
>
> if (int_stat == PCH_STATUS_INT) {
> reg_stat = ioread32(&priv->regs->stat);
> - if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
> - if (reg_stat & PCH_BUS_OFF ||
> - (reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL) {
> - pch_can_error(ndev, reg_stat);
> - quota--;
> - }
> - }
>
> - if (reg_stat & PCH_TX_OK)
> - pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
> + if ((reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) &&
> + ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)) {
> + pch_can_error(ndev, reg_stat);
> + quota--;
> + }
>
> - if (reg_stat & PCH_RX_OK)
> - pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
> + if (reg_stat & (PCH_TX_OK | PCH_RX_OK))
> + pch_can_bit_clear(&priv->regs->stat,
> + reg_stat & (PCH_TX_OK | PCH_RX_OK));
>
> int_stat = pch_can_int_pending(priv);
> }
> @@ -900,14 +897,13 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
>
> + tx_obj_no = priv->tx_obj;
> if (priv->tx_obj == PCH_TX_OBJ_END) {
> if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
> netif_stop_queue(ndev);
>
> - tx_obj_no = priv->tx_obj;
> priv->tx_obj = PCH_TX_OBJ_START;
> } else {
> - tx_obj_no = priv->tx_obj;
> priv->tx_obj++;
> }
>
> @@ -926,9 +922,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> id2 |= PCH_ID_MSGVAL;
>
> /* If remote frame has to be transmitted.. */
> - if (cf->can_id & CAN_RTR_FLAG)
> - id2 &= ~PCH_ID2_DIR;
> - else
> + if (!(cf->can_id & CAN_RTR_FLAG))
> id2 |= PCH_ID2_DIR;
>
> iowrite32(id2, &priv->regs->ifregs[1].id2);
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: [PATCH net-next-2.6 v8 01/20] CAN : Add flow control processing.
From: Marc Kleine-Budde @ 2010-12-12 15:26 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
qi.wang-ral2JQCrhuEAvxtiuMwx3w,
margie.foster-ral2JQCrhuEAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w,
joel.clark-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger
In-Reply-To: <4CFE13E4.2020707-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 3115 bytes --]
On 12/07/2010 12:00 PM, Tomoya MORINAGA wrote:
> Currently, there is no flow control processing.
> Thus, Add flow control processing as
> when there is no empty of tx buffer,
> netif_stop_queue is called.
> When there is empty buffer, netif_wake_queue is called.
See comment inline.
> Signed-off-by: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> ---
> drivers/net/can/pch_can.c | 31 ++++++++++++-------------------
> 1 files changed, 12 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index a9b6a65..f0f1404 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -102,6 +102,10 @@
>
> #define PCH_FIFO_THRESH 16
>
> +/* TxRqst2 show status of MsgObjNo.17~32 */
> +#define PCH_TREQ2_TX_MASK (((1 << PCH_TX_OBJ_NUM) - 1) <<\
> + (PCH_RX_OBJ_END - 16))
> +
> enum pch_ifreg {
> PCH_RX_IFREG,
> PCH_TX_IFREG,
> @@ -871,6 +875,8 @@ MSG_OBJ:
> dlc = 8;
> stats->tx_bytes += dlc;
> stats->tx_packets++;
> + if (int_stat == PCH_TX_OBJ_END)
> + netif_wake_queue(ndev);
> }
>
> int_stat = pch_can_int_pending(priv);
> @@ -1009,18 +1015,6 @@ static int pch_close(struct net_device *ndev)
> return 0;
> }
>
> -static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
> -{
> - u32 buffer_status = 0;
> - struct pch_can_priv *priv = netdev_priv(ndev);
> -
> - /* Getting the message object status. */
> - buffer_status = (u32) pch_can_get_buffer_status(priv);
> -
> - return buffer_status & obj_id;
> -}
> -
> -
> static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> {
> int i, j;
> @@ -1031,17 +1025,16 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
>
> - if (priv->tx_obj == PCH_TX_OBJ_END) { /* Point tail Obj */
> - while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
> - PCH_RX_OBJ_NUM)))
> - udelay(500);
> + if (priv->tx_obj == PCH_TX_OBJ_END) {
> + if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
> + netif_stop_queue(ndev);
David asked you in his previous review to implement a pure software
solution without relying on the hardware because it tends to be racy.
>
> - priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj ID */
> - tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */
> + tx_buffer_avail = priv->tx_obj;
> + priv->tx_obj = PCH_TX_OBJ_START;
> } else {
> tx_buffer_avail = priv->tx_obj;
> + priv->tx_obj++;
> }
> - priv->tx_obj++;
>
> /* Reading the Msg Obj from the Msg RAM to the Interface register. */
> iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask);
cheers, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: [PATCH net-next-2.6 v8 03/20] CAN : Fix endianness issue.
From: Marc Kleine-Budde @ 2010-12-12 15:30 UTC (permalink / raw)
To: Tomoya MORINAGA
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
qi.wang-ral2JQCrhuEAvxtiuMwx3w,
margie.foster-ral2JQCrhuEAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w,
joel.clark-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger
In-Reply-To: <4CFE1489.4030808-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 5298 bytes --]
On 12/07/2010 12:03 PM, Tomoya MORINAGA wrote:
> there is endianness issue both Tx and Rx.
> Currently, data is set like below.
> Register:
> MSB--LSB
> x x D0 D1
> x x D2 D3
> x x D4 D5
> x x D6 D7
>
> But Data to be sent must be set like below.
> Register:
> MSB--LSB
> x x D1 D0
> x x D3 D2
> x x D5 D4
> x x D7 D6 (x means reserved area.)
Nitpick inline, please fix it, then add my Acked-by
Marc
> Signed-off-by: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> ---
> drivers/net/can/pch_can.c | 47 +++++++++++++++++++-------------------------
> 1 files changed, 20 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 0b6d4f4..b17ca0c 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -138,10 +138,7 @@ struct pch_can_if_regs {
> u32 id1;
> u32 id2;
> u32 mcont;
> - u32 dataa1;
> - u32 dataa2;
> - u32 datab1;
> - u32 datab2;
> + u32 data[4];
> u32 rsv[13];
> };
>
> @@ -424,10 +421,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[0].id1);
> iowrite32(0x0, &priv->regs->ifregs[0].id2);
> iowrite32(0x0, &priv->regs->ifregs[0].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[0].cmask);
> @@ -441,10 +438,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[1].id1);
> iowrite32(0x0, &priv->regs->ifregs[1].id2);
> iowrite32(0x0, &priv->regs->ifregs[1].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[1].cmask);
> @@ -707,12 +704,13 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
> canid_t id;
> u32 ide;
> u32 rtr;
> - int i, j, k;
> + int i, k;
> int rcv_pkts = 0;
> struct sk_buff *skb;
> struct can_frame *cf;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct net_device_stats *stats = &(priv->ndev->stats);
> + u16 data_reg;
>
> /* Reading the messsage object from the Message RAM */
> iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> @@ -778,12 +776,10 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
> ((ioread32(&priv->regs->ifregs[0].mcont)) & 0x0f);
> }
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - reg = ioread32(&priv->regs->ifregs[0].dataa1 + j*4);
> - cf->data[i++] = cpu_to_le32(reg & 0xff);
> - if (i == cf->can_dlc)
> - break;
> - cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
> + cf->data[i] = data_reg & 0xff;
The & 0xff is not needed cf->data is only 8bit wide.
> + cf->data[i + 1] = data_reg >> 8;
> }
>
> netif_receive_skb(skb);
> @@ -1016,10 +1012,10 @@ static int pch_close(struct net_device *ndev)
>
> static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> {
> - int i, j;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct can_frame *cf = (struct can_frame *)skb->data;
> int tx_buffer_avail = 0;
> + int i;
>
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
> @@ -1060,13 +1056,10 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> if (cf->can_id & CAN_RTR_FLAG)
> pch_can_bit_clear(&priv->regs->ifregs[1].id2, PCH_ID2_DIR);
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - iowrite32(le32_to_cpu(cf->data[i++]),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> - if (i == cf->can_dlc)
> - break;
> - iowrite32(le32_to_cpu(cf->data[i++] << 8),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> + /* Copy data to register */
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + iowrite16(cf->data[i] | (cf->data[i + 1] << 8),
> + &priv->regs->ifregs[1].data[i / 2]);
> }
>
> can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_END - 1);
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: Loopback performance from kernel 2.6.12 to 2.6.37
From: Arnaldo Carvalho de Melo @ 2010-12-12 15:48 UTC (permalink / raw)
To: Jesper Dangaard Brouer; +Cc: Eric Dumazet, netdev
In-Reply-To: <1289388256.15004.66.camel@firesoul.comx.local>
Em Wed, Nov 10, 2010 at 12:24:16PM +0100, Jesper Dangaard Brouer escreveu:
> > BUT perf top reveals that its probably related to the function
> > 'find_busiest_group' ... any kernel config hints how I get rid of that?
>
> The 'find_busiest_group' seems to be an artifact of "perf top", if I use
> "perf record" then the 'find_busiest_group' function disappears. Which
> is kind of strange, as 'find_busiest_group' seem the be related to
> sched_fair.c.
>
> perf --version
> perf version 2.6.35.7.1.g60d9c
perf top does sytemwide sampling, while when you use 'perf record
./workload' its not systemwide.
Take a look at 'perf top --help' to see how to limit this to an existing
pid, tid, cpu list, etc.
- Arnaldo
^ permalink raw reply
* [PATCH 1/9] drivers/net: remove unnecessary flush_scheduled_work() calls
From: Tejun Heo @ 2010-12-12 15:52 UTC (permalink / raw)
To: linux-kernel, netdev, davem
Cc: Tejun Heo, Wolfgang Grandegger, Stephen Hemminger,
Ramkrishna Vepa, Sivakumar Subramani, Sreenivasa Honnur,
Jon Mason
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
janz-ican3, sh_eth, skge and vxge don't use workqueue at all and there
is no reason to flush the system_wq. Drop flush_scheduled_work()
calls and references to workqueue.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Wolfgang Grandegger <wg@grandegger.com>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Ramkrishna Vepa <ramkrishna.vepa@exar.com>
Cc: Sivakumar Subramani <sivakumar.subramani@exar.com>
Cc: Sreenivasa Honnur <sreenivasa.honnur@exar.com>
Cc: Jon Mason <jon.mason@exar.com>
Cc: netdev@vger.kernel.org
---
drivers/net/can/janz-ican3.c | 9 ---------
drivers/net/sh_eth.c | 1 -
drivers/net/sh_eth.h | 1 -
drivers/net/skge.c | 2 --
drivers/net/vxge/vxge-main.c | 2 --
5 files changed, 0 insertions(+), 15 deletions(-)
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 6e533dc..b9a6d7a 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -1114,11 +1114,6 @@ static bool ican3_txok(struct ican3_dev *mod)
/*
* Recieve one CAN frame from the hardware
*
- * This works like the core of a NAPI function, but is intended to be called
- * from workqueue context instead. This driver already needs a workqueue to
- * process control messages, so we use the workqueue instead of using NAPI.
- * This was done to simplify locking.
- *
* CONTEXT: must be called from user context
*/
static int ican3_recv_skb(struct ican3_dev *mod)
@@ -1251,7 +1246,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)
* Reset an ICAN module to its power-on state
*
* CONTEXT: no network device registered
- * LOCKING: work function disabled
*/
static int ican3_reset_module(struct ican3_dev *mod)
{
@@ -1262,9 +1256,6 @@ static int ican3_reset_module(struct ican3_dev *mod)
/* disable interrupts so no more work is scheduled */
iowrite8(1 << mod->num, &mod->ctrl->int_disable);
- /* flush any pending work */
- flush_scheduled_work();
-
/* the first unallocated page in the DPM is #9 */
mod->free_page = DPM_FREE_START;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index b12660d..819c175 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1552,7 +1552,6 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
sh_mdio_release(ndev);
unregister_netdev(ndev);
- flush_scheduled_work();
pm_runtime_disable(&pdev->dev);
free_netdev(ndev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index 8b47763..efa6422 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -26,7 +26,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
-#include <linux/workqueue.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 220e039..8c1404b 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -4012,8 +4012,6 @@ static void __devexit skge_remove(struct pci_dev *pdev)
if (!hw)
return;
- flush_scheduled_work();
-
dev1 = hw->dev[1];
if (dev1)
unregister_netdev(dev1);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index b771e4b..537ad87 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -3439,8 +3439,6 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev)
strncpy(buf, dev->name, IFNAMSIZ);
- flush_scheduled_work();
-
/* in 2.6 will call stop() if device is up */
unregister_netdev(dev);
--
1.7.1
^ permalink raw reply related
* [PATCH 3/9] ehea: kill unused ehea_rereg_mr_task
From: Tejun Heo @ 2010-12-12 15:52 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, Breno Leitao
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
ehea_rereg_mr_task is not used. Remove it and drop @work parameter
from ehea_rereg_mrs().
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Breno Leitao <leitao@linux.vnet.ibm.com>
Cc: netdev@vger.kernel.org
---
drivers/net/ehea/ehea.h | 2 --
drivers/net/ehea/ehea_main.c | 9 +++------
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8e745e7..1f2a675 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -515,6 +515,4 @@ void ehea_set_ethtool_ops(struct net_device *netdev);
int ehea_sense_port_attr(struct ehea_port *port);
int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
-extern struct work_struct ehea_rereg_mr_task;
-
#endif /* __EHEA_H__ */
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 69f6152..d51def1 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -101,7 +101,6 @@ MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
static int port_name_cnt;
static LIST_HEAD(adapter_list);
static unsigned long ehea_driver_flags;
-struct work_struct ehea_rereg_mr_task;
static DEFINE_MUTEX(dlpar_mem_lock);
struct ehea_fw_handle_array ehea_fw_handles;
struct ehea_bcmc_reg_array ehea_bcmc_regs;
@@ -2984,7 +2983,7 @@ out:
mutex_unlock(&dlpar_mem_lock);
}
-static void ehea_rereg_mrs(struct work_struct *work)
+static void ehea_rereg_mrs(void)
{
int ret, i;
struct ehea_adapter *adapter;
@@ -3659,14 +3658,14 @@ static int ehea_mem_notifier(struct notifier_block *nb,
set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
goto out_unlock;
- ehea_rereg_mrs(NULL);
+ ehea_rereg_mrs();
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))
goto out_unlock;
- ehea_rereg_mrs(NULL);
+ ehea_rereg_mrs();
break;
default:
break;
@@ -3742,8 +3741,6 @@ int __init ehea_module_init(void)
printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
DRV_VERSION);
-
- INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
--
1.7.1
^ permalink raw reply related
* [PATCH 4/9] ehea: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, Breno Leitao
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
Directly cancel port->reset_task from ehea_shutdown_single_port()
instead. As this cancels the work for each port on driver detach,
flushing system_wq from ehea_remove() or ehea_module_exit() is no
longer necessary.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Breno Leitao <leitao@linux.vnet.ibm.com>
Cc: netdev@vger.kernel.org
---
drivers/net/ehea/ehea_main.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index d51def1..81e5b7b 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -3318,6 +3318,8 @@ out_err:
static void ehea_shutdown_single_port(struct ehea_port *port)
{
struct ehea_adapter *adapter = port->adapter;
+
+ cancel_work_sync(&port->reset_task);
unregister_netdev(port->netdev);
ehea_unregister_port(port);
kfree(port->mc_list);
@@ -3607,8 +3609,6 @@ static int __devexit ehea_remove(struct platform_device *dev)
ehea_remove_device_sysfs(dev);
- flush_scheduled_work();
-
ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
tasklet_kill(&adapter->neq_tasklet);
@@ -3797,7 +3797,6 @@ static void __exit ehea_module_exit(void)
{
int ret;
- flush_scheduled_work();
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
unregister_reboot_notifier(&ehea_reboot_nb);
--
1.7.1
^ permalink raw reply related
* [PATCH 7/9] sungem: update gp->reset_task flushing
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
gp->reset_task_pending is always set right before reset_task is
scheduled and as there is no synchronization between the setting and
scheduling, busy looping on reset_task_pending before flushing
reset_task doesn't really buy anything.
Directly flush gp->reset_task on suspend and cancel on detach.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
drivers/net/sungem.c | 12 ++++--------
1 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 4ceb3cf..9e992ca 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2380,10 +2380,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
*/
mutex_unlock(&gp->pm_mutex);
- /* Wait for a pending reset task to complete */
- while (gp->reset_task_pending)
- yield();
- flush_scheduled_work();
+ /* Wait for the pending reset task to complete */
+ flush_work_sync(&gp->reset_task);
/* Shut the PHY down eventually and setup WOL */
gem_stop_phy(gp, gp->asleep_wol);
@@ -2928,10 +2926,8 @@ static void gem_remove_one(struct pci_dev *pdev)
/* We shouldn't need any locking here */
gem_get_cell(gp);
- /* Wait for a pending reset task to complete */
- while (gp->reset_task_pending)
- yield();
- flush_scheduled_work();
+ /* Cancel reset task */
+ cancel_work_sync(&gp->reset_task);
/* Shut the PHY down */
gem_stop_phy(gp, 0);
--
1.7.1
^ permalink raw reply related
* [PATCH 9/9] hostap: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, Jes Sorensen
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
flush_scheduled_work() is on its way out. Drop flush_scheduled_work()
from prism2_free_local_data() and replace it with explicit flushing of
work items on the respective free functions. Work items in ap_data
are flushed from hostap_free_data() and the ones in local_info from
prism2_free_local_data().
Flush is used instead of cancel as some process and free items from
queue.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jes Sorensen <jes@trained-monkey.org>
Cc: netdev@vger.kernel.org
---
drivers/net/wireless/hostap/hostap_ap.c | 3 +++
drivers/net/wireless/hostap/hostap_hw.c | 8 +++++++-
2 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index dbb9869..18d63f5 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -858,7 +858,10 @@ void hostap_free_data(struct ap_data *ap)
return;
}
+ flush_work_sync(&ap->add_sta_proc_queue);
+
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ flush_work_sync(&ap->wds_oper_queue);
if (ap->crypt)
ap->crypt->deinit(ap->crypt_priv);
ap->crypt = ap->crypt_priv = NULL;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index b7cb165..a8bddd8 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3317,7 +3317,13 @@ static void prism2_free_local_data(struct net_device *dev)
unregister_netdev(local->dev);
- flush_scheduled_work();
+ flush_work_sync(&local->reset_queue);
+ flush_work_sync(&local->set_multicast_list_queue);
+ flush_work_sync(&local->set_tim_queue);
+#ifndef PRISM2_NO_STATION_MODES
+ flush_work_sync(&local->info_queue);
+#endif
+ flush_work_sync(&local->comms_qual_update);
lib80211_crypt_info_free(&local->crypt_info);
--
1.7.1
^ permalink raw reply related
* [PATCHSET] net-dev: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:52 UTC (permalink / raw)
To: linux-kernel, netdev, davem
Hello,
This patchset removes the use of flush_scheduled_work(), which is
being deprecated, from various network drivers. It contains the
following nine patches.
0001-drivers-net-remove-unnecessary-flush_scheduled_work-.patch
0002-drivers-net-don-t-use-flush_scheduled_work.patch
0003-ehea-kill-unused-ehea_rereg_mr_task.patch
0004-ehea-don-t-use-flush_scheduled_work.patch
0005-iseries_veth-don-t-use-flush_scheduled_work.patch
0006-igb-v-ixgbe-don-t-use-flush_scheduled_work.patch
0007-sungem-update-gp-reset_task-flushing.patch
0008-i2400m-drop-i2400m_schedule_work.patch
0009-hostap-don-t-use-flush_scheduled_work.patch
0001 and 0002 are straight forward conversions across multiple network
drivers. The rest are a bit more involved per-driver or driver family
conversions.
This patchset is on top of the current net-next-2.6.git#master
(ad1184c6cf067a13e8cb2a4e7ccc407f947027d0) and available in the
following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git net-dev-kill-flush_scheduled_work
diffstat follows. Thanks.
drivers/net/8139too.c | 3 -
drivers/net/atlx/atl2.c | 4 -
drivers/net/bcm63xx_enet.c | 2
drivers/net/bnx2.c | 4 -
drivers/net/can/janz-ican3.c | 9 ---
drivers/net/cassini.c | 4 -
drivers/net/cxgb3/cxgb3_main.c | 3 -
drivers/net/e1000e/netdev.c | 6 +-
drivers/net/ehea/ehea.h | 2
drivers/net/ehea/ehea_main.c | 14 +---
drivers/net/enic/enic_main.c | 2
drivers/net/ibm_newemac/core.c | 2
drivers/net/igb/igb_main.c | 9 ++-
drivers/net/igbvf/netdev.c | 7 +-
drivers/net/irda/mcs7780.c | 2
drivers/net/iseries_veth.c | 18 +-----
drivers/net/ixgb/ixgb_main.c | 2
drivers/net/ixgbe/ixgbe_main.c | 11 ++-
drivers/net/ixgbevf/ixgbevf_main.c | 3 -
drivers/net/mv643xx_eth.c | 2
drivers/net/myri10ge/myri10ge.c | 2
drivers/net/niu.c | 2
drivers/net/pxa168_eth.c | 2
drivers/net/r8169.c | 2
drivers/net/s2io.c | 6 +-
drivers/net/sh_eth.c | 1
drivers/net/sh_eth.h | 1
drivers/net/sis190.c | 3 -
drivers/net/skge.c | 2
drivers/net/sungem.c | 12 +---
drivers/net/tg3.c | 4 -
drivers/net/usb/sierra_net.c | 5 -
drivers/net/usb/usbnet.c | 3 -
drivers/net/vmxnet3/vmxnet3_drv.c | 2
drivers/net/vxge/vxge-main.c | 2
drivers/net/wimax/i2400m/driver.c | 96 +++++---------------------------
drivers/net/wimax/i2400m/i2400m.h | 19 +-----
drivers/net/wimax/i2400m/sdio.c | 1
drivers/net/wimax/i2400m/usb.c | 1
drivers/net/wireless/hostap/hostap_ap.c | 3 +
drivers/net/wireless/hostap/hostap_hw.c | 8 ++
41 files changed, 97 insertions(+), 189 deletions(-)
--
tejun
^ permalink raw reply
* [PATCH 8/9] i2400m: drop i2400m_schedule_work()
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, Inaky Perez-Gonzalez, linux-wimax
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
i2400m implements dynamic work allocation and queueing mechanism in
i2400_schedule_work(); however, this is only used for reset and
recovery which can be served equally well with preallocated per device
works.
Replace i2400m_schedule_work() with two work structs in struct i2400m.
These works are explicitly canceled when the device is released making
calls to flush_scheduled_work(), which is being deprecated,
unnecessary.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
Cc: linux-wimax@intel.com
Cc: netdev@vger.kernel.org
---
drivers/net/wimax/i2400m/driver.c | 96 ++++++------------------------------
drivers/net/wimax/i2400m/i2400m.h | 19 ++-----
drivers/net/wimax/i2400m/sdio.c | 1 -
drivers/net/wimax/i2400m/usb.c | 1 -
4 files changed, 21 insertions(+), 96 deletions(-)
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index cdedab4..f060332 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -92,54 +92,6 @@ MODULE_PARM_DESC(barkers,
"signal; values are appended to a list--setting one value "
"as zero cleans the existing list and starts a new one.");
-static
-struct i2400m_work *__i2400m_work_setup(
- struct i2400m *i2400m, void (*fn)(struct work_struct *),
- gfp_t gfp_flags, const void *pl, size_t pl_size)
-{
- struct i2400m_work *iw;
-
- iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags);
- if (iw == NULL)
- return NULL;
- iw->i2400m = i2400m_get(i2400m);
- iw->pl_size = pl_size;
- memcpy(iw->pl, pl, pl_size);
- INIT_WORK(&iw->ws, fn);
- return iw;
-}
-
-
-/*
- * Schedule i2400m's specific work on the system's queue.
- *
- * Used for a few cases where we really need it; otherwise, identical
- * to i2400m_queue_work().
- *
- * Returns < 0 errno code on error, 1 if ok.
- *
- * If it returns zero, something really bad happened, as it means the
- * works struct was already queued, but we have just allocated it, so
- * it should not happen.
- */
-static int i2400m_schedule_work(struct i2400m *i2400m,
- void (*fn)(struct work_struct *), gfp_t gfp_flags,
- const void *pl, size_t pl_size)
-{
- int result;
- struct i2400m_work *iw;
-
- result = -ENOMEM;
- iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size);
- if (iw != NULL) {
- result = schedule_work(&iw->ws);
- if (WARN_ON(result == 0))
- result = -ENXIO;
- }
- return result;
-}
-
-
/*
* WiMAX stack operation: relay a message from user space
*
@@ -648,17 +600,11 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset);
static
void __i2400m_dev_reset_handle(struct work_struct *ws)
{
- int result;
- struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
- const char *reason;
- struct i2400m *i2400m = iw->i2400m;
+ struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws);
+ const char *reason = i2400m->reset_reason;
struct device *dev = i2400m_dev(i2400m);
struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;
-
- if (WARN_ON(iw->pl_size != sizeof(reason)))
- reason = "SW BUG: reason n/a";
- else
- memcpy(&reason, iw->pl, sizeof(reason));
+ int result;
d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason);
@@ -733,8 +679,6 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)
}
}
out:
- i2400m_put(i2400m);
- kfree(iw);
d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n",
ws, i2400m, reason);
}
@@ -754,8 +698,8 @@ out:
*/
int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason)
{
- return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
- GFP_ATOMIC, &reason, sizeof(reason));
+ i2400m->reset_reason = reason;
+ return schedule_work(&i2400m->reset_ws);
}
EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
@@ -768,14 +712,9 @@ EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
static
void __i2400m_error_recovery(struct work_struct *ws)
{
- struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
- struct i2400m *i2400m = iw->i2400m;
+ struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws);
i2400m_reset(i2400m, I2400M_RT_BUS);
-
- i2400m_put(i2400m);
- kfree(iw);
- return;
}
/*
@@ -805,18 +744,10 @@ void __i2400m_error_recovery(struct work_struct *ws)
*/
void i2400m_error_recovery(struct i2400m *i2400m)
{
- struct device *dev = i2400m_dev(i2400m);
-
- if (atomic_add_return(1, &i2400m->error_recovery) == 1) {
- if (i2400m_schedule_work(i2400m, __i2400m_error_recovery,
- GFP_ATOMIC, NULL, 0) < 0) {
- dev_err(dev, "run out of memory for "
- "scheduling an error recovery ?\n");
- atomic_dec(&i2400m->error_recovery);
- }
- } else
+ if (atomic_add_return(1, &i2400m->error_recovery) == 1)
+ schedule_work(&i2400m->recovery_ws);
+ else
atomic_dec(&i2400m->error_recovery);
- return;
}
EXPORT_SYMBOL_GPL(i2400m_error_recovery);
@@ -886,6 +817,10 @@ void i2400m_init(struct i2400m *i2400m)
mutex_init(&i2400m->init_mutex);
/* wake_tx_ws is initialized in i2400m_tx_setup() */
+
+ INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle);
+ INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery);
+
atomic_set(&i2400m->bus_reset_retries, 0);
i2400m->alive = 0;
@@ -1040,6 +975,9 @@ void i2400m_release(struct i2400m *i2400m)
i2400m_dev_stop(i2400m);
+ cancel_work_sync(&i2400m->reset_ws);
+ cancel_work_sync(&i2400m->recovery_ws);
+
i2400m_debugfs_rm(i2400m);
sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj,
&i2400m_dev_attr_group);
@@ -1083,8 +1021,6 @@ module_init(i2400m_driver_init);
static
void __exit i2400m_driver_exit(void)
{
- /* for scheds i2400m_dev_reset_handle() */
- flush_scheduled_work();
i2400m_barker_db_exit();
}
module_exit(i2400m_driver_exit);
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 59ac770..17ecaa4 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -632,6 +632,11 @@ struct i2400m {
struct work_struct wake_tx_ws;
struct sk_buff *wake_tx_skb;
+ struct work_struct reset_ws;
+ const char *reset_reason;
+
+ struct work_struct recovery_ws;
+
struct dentry *debugfs_dentry;
const char *fw_name; /* name of the current firmware image */
unsigned long fw_version; /* version of the firmware interface */
@@ -896,20 +901,6 @@ struct device *i2400m_dev(struct i2400m *i2400m)
return i2400m->wimax_dev.net_dev->dev.parent;
}
-/*
- * Helper for scheduling simple work functions
- *
- * This struct can get any kind of payload attached (normally in the
- * form of a struct where you pack the stuff you want to pass to the
- * _work function).
- */
-struct i2400m_work {
- struct work_struct ws;
- struct i2400m *i2400m;
- size_t pl_size;
- u8 pl[0];
-};
-
extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
char *, size_t);
extern int i2400m_msg_size_check(struct i2400m *,
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 9bfc26e..be428ca 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -590,7 +590,6 @@ module_init(i2400ms_driver_init);
static
void __exit i2400ms_driver_exit(void)
{
- flush_scheduled_work(); /* for the stuff we schedule */
sdio_unregister_driver(&i2400m_sdio_driver);
}
module_exit(i2400ms_driver_exit);
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index d3365ac..10e3ab3 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -780,7 +780,6 @@ module_init(i2400mu_driver_init);
static
void __exit i2400mu_driver_exit(void)
{
- flush_scheduled_work(); /* for the stuff we schedule from sysfs.c */
usb_deregister(&i2400mu_driver);
}
module_exit(i2400mu_driver_exit);
--
1.7.1
^ permalink raw reply related
* [PATCH 6/9] igb[v],ixgbe: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, e1000-devel
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
All three drivers use flush_scheduled_work() similarly during driver
detach. Replace it with explicit cancels.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: e1000-devel@lists.sourceforge.net
Cc: netdev@vger.kernel.org
---
drivers/net/igb/igb_main.c | 9 ++++++---
drivers/net/igbvf/netdev.c | 7 ++++---
drivers/net/ixgbe/ixgbe_main.c | 11 +++++++----
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 041f8e6..62348fc 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2050,13 +2050,16 @@ static void __devexit igb_remove(struct pci_dev *pdev)
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- /* flush_scheduled work may reschedule our watchdog task, so
- * explicitly disable watchdog tasks from being rescheduled */
+ /*
+ * The watchdog timer may be rescheduled, so explicitly
+ * disable watchdog from being rescheduled.
+ */
set_bit(__IGB_DOWN, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
- flush_scheduled_work();
+ cancel_work_sync(&adapter->reset_task);
+ cancel_work_sync(&adapter->watchdog_task);
#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 8dbde23..4fb023b 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -2825,13 +2825,14 @@ static void __devexit igbvf_remove(struct pci_dev *pdev)
struct e1000_hw *hw = &adapter->hw;
/*
- * flush_scheduled work may reschedule our watchdog task, so
- * explicitly disable watchdog tasks from being rescheduled
+ * The watchdog timer may be rescheduled, so explicitly
+ * disable it from being rescheduled.
*/
set_bit(__IGBVF_DOWN, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
- flush_scheduled_work();
+ cancel_work_sync(&adapter->reset_task);
+ cancel_work_sync(&adapter->watchdog_task);
unregister_netdev(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 8af0fc0..ca9036d 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -7373,13 +7373,15 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
struct net_device *netdev = adapter->netdev;
set_bit(__IXGBE_DOWN, &adapter->state);
- /* clear the module not found bit to make sure the worker won't
- * reschedule
+
+ /*
+ * The timers may be rescheduled, so explicitly disable them
+ * from being rescheduled.
*/
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
-
del_timer_sync(&adapter->sfp_timer);
+
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->sfp_task);
cancel_work_sync(&adapter->multispeed_fiber_task);
@@ -7387,7 +7389,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
- flush_scheduled_work();
+ if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
+ cancel_work_sync(&adapter->check_overtemp_task);
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
--
1.7.1
^ permalink raw reply related
* [PATCH 5/9] iseries_veth: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:53 UTC (permalink / raw)
To: linux-kernel, netdev, davem; +Cc: Tejun Heo, Santiago Leon
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
flush_scheduled_work() is on its way out. Remove its usage from
iseries_veth.
* Cancelling a delayed work, queueing it for immediate execution if
cancelled and then waiting for completion can be done by simply
calling flush_delayed_work_sync().
* Explicitly cancel cnx->statemachine_wq on module unload.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Santiago Leon <santil@linux.vnet.ibm.com>
Cc: netdev@vger.kernel.org
---
drivers/net/iseries_veth.c | 18 ++++--------------
1 files changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 63ac531..9ece1fd 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -885,17 +885,8 @@ static void veth_stop_connection(struct veth_lpar_connection *cnx)
veth_kick_statemachine(cnx);
spin_unlock_irq(&cnx->lock);
- /* There's a slim chance the reset code has just queued the
- * statemachine to run in five seconds. If so we need to cancel
- * that and requeue the work to run now. */
- if (cancel_delayed_work(&cnx->statemachine_wq)) {
- spin_lock_irq(&cnx->lock);
- veth_kick_statemachine(cnx);
- spin_unlock_irq(&cnx->lock);
- }
-
- /* Wait for the state machine to run. */
- flush_scheduled_work();
+ /* ensure the statemachine runs now and waits for its completion */
+ flush_delayed_work_sync(&cnx->statemachine_wq);
}
static void veth_destroy_connection(struct veth_lpar_connection *cnx)
@@ -1653,15 +1644,14 @@ static void __exit veth_module_cleanup(void)
/* Disconnect our "irq" to stop events coming from the Hypervisor. */
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
- /* Make sure any work queued from Hypervisor callbacks is finished. */
- flush_scheduled_work();
-
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
cnx = veth_cnx[i];
if (!cnx)
continue;
+ /* Cancel work queued from Hypervisor callbacks */
+ cancel_delayed_work_sync(&cnx->statemachine_wq);
/* Remove the connection from sysfs */
kobject_del(&cnx->kobject);
/* Drop the driver's reference to the connection */
--
1.7.1
^ permalink raw reply related
* [PATCH 2/9] drivers/net: don't use flush_scheduled_work()
From: Tejun Heo @ 2010-12-12 15:52 UTC (permalink / raw)
To: linux-kernel, netdev, davem
Cc: Tejun Heo, Jay Cliburn, Michael Chan, Divy Le Ray, e1000-devel,
Vasanthy Kolluri, Samuel Ortiz, Lennert Buytenhek,
Andrew Gallatin, Francois Romieu, Ramkrishna Vepa, Matt Carlson,
David Brownell, Shreyas Bhatewara
In-Reply-To: <1292169185-10579-1-git-send-email-tj@kernel.org>
flush_scheduled_work() is on its way out. This patch contains simple
conversions to replace flush_scheduled_work() usage with direct
cancels and flushes.
Directly cancel the used works on driver detach and flush them in
other cases.
The conversions are mostly straight forward and the only dangers are,
* Forgetting to cancel/flush one or more used works.
* Cancelling when a work should be flushed (ie. the work must be
executed once scheduled whether the driver is detaching or not).
I've gone over the changes multiple times but it would be much
appreciated if you can review with the above points in mind.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jay Cliburn <jcliburn@gmail.com>
Cc: Michael Chan <mchan@broadcom.com>
Cc: Divy Le Ray <divy@chelsio.com>
Cc: e1000-devel@lists.sourceforge.net
Cc: Vasanthy Kolluri <vkolluri@cisco.com>
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Andrew Gallatin <gallatin@myri.com>
Cc: Francois Romieu <romieu@fr.zoreil.com>
Cc: Ramkrishna Vepa <ramkrishna.vepa@exar.com>
Cc: Matt Carlson <mcarlson@broadcom.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
Cc: netdev@vger.kernel.org
---
drivers/net/8139too.c | 3 ++-
drivers/net/atlx/atl2.c | 4 ++--
drivers/net/bcm63xx_enet.c | 2 +-
drivers/net/bnx2.c | 4 ++--
drivers/net/cassini.c | 4 ++--
drivers/net/cxgb3/cxgb3_main.c | 3 ++-
drivers/net/e1000e/netdev.c | 6 +++---
drivers/net/enic/enic_main.c | 2 +-
drivers/net/ibm_newemac/core.c | 2 +-
drivers/net/irda/mcs7780.c | 2 +-
drivers/net/ixgb/ixgb_main.c | 2 +-
drivers/net/ixgbevf/ixgbevf_main.c | 3 +--
drivers/net/mv643xx_eth.c | 2 +-
drivers/net/myri10ge/myri10ge.c | 2 +-
drivers/net/niu.c | 2 +-
drivers/net/pxa168_eth.c | 2 +-
drivers/net/r8169.c | 2 +-
drivers/net/s2io.c | 6 ++++--
drivers/net/sis190.c | 3 ++-
drivers/net/tg3.c | 4 ++--
drivers/net/usb/sierra_net.c | 5 ++---
drivers/net/usb/usbnet.c | 3 +--
drivers/net/vmxnet3/vmxnet3_drv.c | 2 +-
23 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index f5166dc..98517a3 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1092,10 +1092,11 @@ err_out:
static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
+ struct rtl8139_private *tp = netdev_priv(dev);
assert (dev != NULL);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&tp->thread);
unregister_netdev (dev);
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 35b14be..4e6f4e9 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -1504,8 +1504,8 @@ static void __devexit atl2_remove(struct pci_dev *pdev)
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_config_timer);
-
- flush_scheduled_work();
+ cancel_work_sync(&adapter->reset_task);
+ cancel_work_sync(&adapter->link_chg_task);
unregister_netdev(netdev);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index ecfef24..e94a966 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -1097,7 +1097,7 @@ static int bcm_enet_stop(struct net_device *dev)
enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
/* make sure no mib update is scheduled */
- flush_scheduled_work();
+ cancel_work_sync(&priv->mib_update_task);
/* disable dma & mac */
bcm_enet_disable_dma(priv, priv->tx_chan);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 03209a3..5c811f3 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -8393,7 +8393,7 @@ bnx2_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);
- flush_scheduled_work();
+ cancel_work_sync(&bp->reset_task);
unregister_netdev(dev);
@@ -8431,7 +8431,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
if (!netif_running(dev))
return 0;
- flush_scheduled_work();
+ cancel_work_sync(&bp->reset_task);
bnx2_netif_stop(bp, true);
netif_device_detach(dev);
del_timer_sync(&bp->timer);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index d6b6d6a..a8a32bc 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -3880,7 +3880,7 @@ static int cas_change_mtu(struct net_device *dev, int new_mtu)
schedule_work(&cp->reset_task);
#endif
- flush_scheduled_work();
+ flush_work_sync(&cp->reset_task);
return 0;
}
@@ -5177,7 +5177,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
vfree(cp->fw_data);
mutex_lock(&cp->pm_mutex);
- flush_scheduled_work();
+ cancel_work_sync(&cp->reset_task);
if (cp->hw_running)
cas_shutdown(cp);
mutex_unlock(&cp->pm_mutex);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 3864617..4d538a4 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1359,6 +1359,7 @@ out:
static int offload_close(struct t3cdev *tdev)
{
struct adapter *adapter = tdev2adap(tdev);
+ struct t3c_data *td = T3C_DATA(tdev);
if (!test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
return 0;
@@ -1369,7 +1370,7 @@ static int offload_close(struct t3cdev *tdev)
sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
/* Flush work scheduled while releasing TIDs */
- flush_scheduled_work();
+ flush_work_sync(&td->tid_release_task);
tdev->lldev = NULL;
cxgb3_set_dummy_ops(tdev);
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 5530d0b..02d093d 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -6028,8 +6028,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
bool down = test_bit(__E1000_DOWN, &adapter->state);
/*
- * flush_scheduled work may reschedule our watchdog task, so
- * explicitly disable watchdog tasks from being rescheduled
+ * The timers may be rescheduled, so explicitly disable them
+ * from being rescheduled.
*/
if (!down)
set_bit(__E1000_DOWN, &adapter->state);
@@ -6040,8 +6040,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->downshift_task);
cancel_work_sync(&adapter->update_phy_task);
+ cancel_work_sync(&adapter->led_blink_task);
cancel_work_sync(&adapter->print_hang_task);
- flush_scheduled_work();
if (!(netdev->flags & IFF_UP))
e1000_power_down_phy(adapter);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 9befd54..77d9138 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -2834,7 +2834,7 @@ static void __devexit enic_remove(struct pci_dev *pdev)
if (netdev) {
struct enic *enic = netdev_priv(netdev);
- flush_scheduled_work();
+ cancel_work_sync(&enic->reset);
unregister_netdev(netdev);
enic_dev_deinit(enic);
vnic_dev_close(enic->vdev);
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 06bb9b7..8f11d29 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2950,7 +2950,7 @@ static int __devexit emac_remove(struct platform_device *ofdev)
unregister_netdev(dev->ndev);
- flush_scheduled_work();
+ cancel_work_sync(&dev->reset_work);
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_detach(dev->tah_dev, dev->tah_port);
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 74b20f1..cc821de 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -959,7 +959,7 @@ static void mcs_disconnect(struct usb_interface *intf)
if (!mcs)
return;
- flush_scheduled_work();
+ cancel_work_sync(&mcs->work);
unregister_netdev(mcs->netdev);
free_netdev(mcs->netdev);
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 2e98506..b021798 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -527,7 +527,7 @@ ixgb_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev_priv(netdev);
- flush_scheduled_work();
+ cancel_work_sync(&adapter->tx_timeout_task);
unregister_netdev(netdev);
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 2216a3c..809e38c 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -3484,10 +3484,9 @@ static void __devexit ixgbevf_remove(struct pci_dev *pdev)
del_timer_sync(&adapter->watchdog_timer);
+ cancel_work_sync(&adapter->reset_task);
cancel_work_sync(&adapter->watchdog_task);
- flush_scheduled_work();
-
if (adapter->netdev_registered) {
unregister_netdev(netdev);
adapter->netdev_registered = false;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index ce31e74..02076e1 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2978,7 +2978,7 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
unregister_netdev(mp->dev);
if (mp->phy != NULL)
phy_detach(mp->phy);
- flush_scheduled_work();
+ cancel_work_sync(&mp->tx_timeout_task);
free_netdev(mp->dev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 8524cc4..1ce0207 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -4067,7 +4067,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
if (mgp == NULL)
return;
- flush_scheduled_work();
+ cancel_work_sync(&mgp->watchdog_work);
netdev = mgp->dev;
unregister_netdev(netdev);
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 781e368..f64c424 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -9917,7 +9917,7 @@ static int niu_suspend(struct pci_dev *pdev, pm_message_t state)
if (!netif_running(dev))
return 0;
- flush_scheduled_work();
+ flush_work_sync(&np->reset_task);
niu_netif_stop(np);
del_timer_sync(&np->timer);
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 04ed27d..1b63c8a 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -1602,7 +1602,7 @@ static int pxa168_eth_remove(struct platform_device *pdev)
mdiobus_unregister(pep->smi_bus);
mdiobus_free(pep->smi_bus);
unregister_netdev(dev);
- flush_scheduled_work();
+ cancel_work_sync(&pep->tx_timeout_task);
free_netdev(dev);
platform_set_drvdata(pdev, NULL);
return 0;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 7d33ef4..98d792c 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -3240,7 +3240,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&tp->task);
unregister_netdev(dev);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 9a1e32f..39c17ce 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -8341,9 +8341,11 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
return;
}
- flush_scheduled_work();
-
sp = netdev_priv(dev);
+
+ cancel_work_sync(&sp->rst_timer_task);
+ cancel_work_sync(&sp->set_link_task);
+
unregister_netdev(dev);
free_shared_mem(sp);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index a5d6a6b..3406ed8 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1915,9 +1915,10 @@ err_release_board:
static void __devexit sis190_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ struct sis190_private *tp = netdev_priv(dev);
sis190_mii_remove(dev);
- flush_scheduled_work();
+ cancel_work_sync(&tp->phy_task);
unregister_netdev(dev);
sis190_release_board(pdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5faa87d..57e19fb 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -15034,7 +15034,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
if (tp->fw)
release_firmware(tp->fw);
- flush_scheduled_work();
+ cancel_work_sync(&tp->reset_task);
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
tg3_phy_fini(tp);
@@ -15073,7 +15073,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
if (!netif_running(dev))
return 0;
- flush_scheduled_work();
+ flush_work_sync(&tp->reset_task);
tg3_phy_stop(tp);
tg3_netif_stop(tp);
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index d1ac15c..ed1b432 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -802,10 +802,9 @@ static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
dev_dbg(&dev->udev->dev, "%s", __func__);
- /* Kill the timer then flush the work queue */
+ /* kill the timer and work */
del_timer_sync(&priv->sync_timer);
-
- flush_scheduled_work();
+ cancel_work_sync(&priv->sierra_net_kevent);
/* tell modem we are going away */
status = sierra_net_send_cmd(dev, priv->shdwn_msg,
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index cff74b8..ed9a416 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1248,8 +1248,7 @@ void usbnet_disconnect (struct usb_interface *intf)
net = dev->net;
unregister_netdev (net);
- /* we don't hold rtnl here ... */
- flush_scheduled_work ();
+ cancel_work_sync(&dev->kevent);
if (dev->driver_info->unbind)
dev->driver_info->unbind (dev, intf);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 65860a9..0169be7 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3069,7 +3069,7 @@ vmxnet3_remove_device(struct pci_dev *pdev)
#endif
num_rx_queues = 1;
- flush_scheduled_work();
+ cancel_work_sync(&adapter->work);
unregister_netdev(netdev);
--
1.7.1
^ permalink raw reply related
* [PATCH update] firewire: net: add carrier detection
From: Stefan Richter @ 2010-12-12 17:09 UTC (permalink / raw)
To: Maxim Levitsky; +Cc: Peter Stuge, linux1394-devel, netdev
In-Reply-To: <1291809485.5421.0.camel@maxim-laptop>
From: Maxim Levitsky <maximlevitsky@gmail.com>
To make userland, e.g. NetworkManager work with firewire, we need to
detect whether cable is plugged or not. Simple and correct way of doing
that is just counting number of peers. No peers - no link and vice
versa.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
Update: Moved netif_carrier_on/off calls into lock-protected sections.
drivers/firewire/net.c | 10 ++++++++++
1 file changed, 10 insertions(+)
Index: b/drivers/firewire/net.c
===================================================================
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -179,6 +179,7 @@ struct fwnet_device {
/* Number of tx datagrams that have been queued but not yet acked */
int queued_datagrams;
+ int peer_count;
struct list_head peer_list;
struct fw_card *card;
struct net_device *netdev;
@@ -1405,6 +1406,10 @@ static int fwnet_change_mtu(struct net_d
return 0;
}
+static const struct ethtool_ops fwnet_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+};
+
static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
@@ -1423,6 +1428,7 @@ static void fwnet_init_dev(struct net_de
net->hard_header_len = FWNET_HLEN;
net->type = ARPHRD_IEEE1394;
net->tx_queue_len = FWNET_TX_QUEUE_LEN;
+ net->ethtool_ops = &fwnet_ethtool_ops;
}
/* caller must hold fwnet_device_mutex */
@@ -1463,6 +1469,8 @@ static int fwnet_add_peer(struct fwnet_d
spin_lock_irq(&dev->lock);
list_add_tail(&peer->peer_link, &dev->peer_list);
+ if (++dev->peer_count > 1)
+ netif_carrier_on(dev->netdev);
spin_unlock_irq(&dev->lock);
return 0;
@@ -1549,6 +1557,8 @@ static void fwnet_remove_peer(struct fwn
spin_lock_irq(&peer->dev->lock);
list_del(&peer->peer_link);
+ if (--peer->dev->peer_count == 1)
+ netif_carrier_off(peer->dev->netdev);
spin_unlock_irq(&peer->dev->lock);
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
--
Stefan Richter
-=====-==-=- ==-- -==--
http://arcgraph.de/sr/
^ permalink raw reply
* Re: System blocks (hangs) on ifconfig up
From: Eric Dumazet @ 2010-12-12 20:29 UTC (permalink / raw)
To: Shmulik Hen; +Cc: netdev
In-Reply-To: <4D04E57C.7020509@trego.co.il>
Le dimanche 12 décembre 2010 à 17:08 +0200, Shmulik Hen a écrit :
> Hello,
>
> My system is Ubuntu 10.04, running kernel 2.6.32-26-generic.
>
> Whenever I try to bring up a specific ethernet interface for the second
> time, my
> system becomes unresponsive for 60 seconds - i.e. no mouse, no keyboard, no
> screen refresh. etc.
>
> Looking at the driver's code, I could see that it's dev->open() method
> calls
> wait_event_interruptible_timeout() with a timeout of 60 seconds - exactly
> the delay I'm seeing.
>
What is this driver ?
> I have narrowed the code to a bare minimum (see below - loosely based on
> dummy.c), which only calls mdelay(10000) in it's dev->open() method, and
> still, my system blocks for exactly 10 seconds when I run the following
> sequence:
>
> > sudo ifconfig shmulik0 up
> > sudo ifconfig shmulik0 down
> > sudo ifconfig shmulik0 up
>
> At this point - the system is stuck for 10 seconds.
>
Certainly not "stuck for 10 seconds"
mdelay(10000) suspends this task for 10 seconds, but other tasks can
certainly run.
However, your shell waits that "ifconfig ... up" finishes.
^ permalink raw reply
* Re: System blocks (hangs) on ifconfig up
From: Eric Dumazet @ 2010-12-12 20:53 UTC (permalink / raw)
To: Shmulik Hen; +Cc: netdev
In-Reply-To: <1292185786.18698.5.camel@edumazet-laptop>
Le dimanche 12 décembre 2010 à 21:29 +0100, Eric Dumazet a écrit :
> Le dimanche 12 décembre 2010 à 17:08 +0200, Shmulik Hen a écrit :
> > Hello,
> >
> > My system is Ubuntu 10.04, running kernel 2.6.32-26-generic.
> >
> > Whenever I try to bring up a specific ethernet interface for the second
> > time, my
> > system becomes unresponsive for 60 seconds - i.e. no mouse, no keyboard, no
> > screen refresh. etc.
> >
> > Looking at the driver's code, I could see that it's dev->open() method
> > calls
> > wait_event_interruptible_timeout() with a timeout of 60 seconds - exactly
> > the delay I'm seeing.
> >
>
> What is this driver ?
>
> > I have narrowed the code to a bare minimum (see below - loosely based on
> > dummy.c), which only calls mdelay(10000) in it's dev->open() method, and
> > still, my system blocks for exactly 10 seconds when I run the following
> > sequence:
> >
> > > sudo ifconfig shmulik0 up
> > > sudo ifconfig shmulik0 down
> > > sudo ifconfig shmulik0 up
> >
> > At this point - the system is stuck for 10 seconds.
> >
>
> Certainly not "stuck for 10 seconds"
>
> mdelay(10000) suspends this task for 10 seconds, but other tasks can
> certainly run.
>
> However, your shell waits that "ifconfig ... up" finishes.
>
>
Oops, I forgot mdelay() was a spin primitive, but was misleading by your
wait_event_interruptible_timeout() previous reference.
Doing mdelay(10000) is certainly very lazy, I hope no driver does
that ...
^ permalink raw reply
* Re: [PATCH] pppoe.c: Fix kernel panic caused by __pppoe_xmit
From: Denys Fedoryshchenko @ 2010-12-12 21:02 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Andrej Ota, Paweł Staszewski, Andrew Morton, netdev,
Paul Mackerras, bugzilla-daemon, bugme-daemon, pstaszewski,
Eric Dumazet, David Miller, Gorik Van Steenberge,
Daniel Kenzelmann
In-Reply-To: <20101211200823.GA1917@del.dom.local>
On Saturday 11 December 2010 22:08:23 Jarek Poplawski wrote:
> On Sat, Dec 11, 2010 at 01:44:38PM +0100, Andrej Ota wrote:
> > __pppoe_xmit function return value was invalid resulting in
> > additional call to kfree_skb on already freed skb. This resulted in
> > memory corruption and consequent kernel panic after PPPoE peer
> > terminated the link.
> >
> > This fixes commit 55c95e738da85373965cb03b4f975d0fd559865b.
> >
> > Signed-off-by: Jarek Poplawski [jarkao2@gmail.com]
> > Signed-off-by: Andrej Ota [andrej@ota.si]
> > Reported-by: Pawel Staszewski [pstaszewski@artcom.pl]
>
> Thanks Andrej! I've only updated emails a bit.
> Jarek P.
>
> Reported-by: Gorik Van Steenberge <gvs@zemos.net>
> Reported-by: Daniel Kenzelmann <kernel.bugzilla@kenzelmann.dyndns.info>
> Reported-by: Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
> Reported-by: Pawel Staszewski <pstaszewski@artcom.pl>
> Diagnosed-by: Andrej Ota <andrej@ota.si>
> Diagnosed-by: Eric Dumazet <eric.dumazet@gmail.com>
> Tested-by: Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
> Tested-by: Pawel Staszewski <pstaszewski@artcom.pl>
> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
> Signed-off-by: Andrej Ota <andrej@ota.si>
Thanks a lot!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox