* Re: bonding: don't increase rx_dropped after processing LACPDUs
From: Jiri Bohac @ 2012-05-04 12:15 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Jiri Bohac, Eric Dumazet, Andy Gospodarek, netdev
In-Reply-To: <1765.1336000239@death.nxdomain>
On Wed, May 02, 2012 at 04:10:39PM -0700, Jay Vosburgh wrote:
> Won't this make it impossible to bind a PF_PACKET socket to
> sll_protocol == ETH_P_SLOW and see the LACPDUs, but only when bonding is
> running 802.3ad?
yes it will...
> This because the ptype_all check in
> __netif_receive_skb happens before the rx_handler, but the ptype_base
> check (bound packet socket, for example) happens after. Currently,
> libpcap looks to bind to ETH_P_ALL, so it won't be affected.
Does it make any sense for the packet socket not to bind to
ETH_P_ALL? With all the rx_handlers interfering with the packet
(e.g. modifying skb->dev, modifying the MAC address), binding to
ETH_P_SLOW will never reliably get you the the original frame
with reliable information about the incoming device.
> If so, is that something we care about?
I think not.
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
^ permalink raw reply
* Re: bonding: don't increase rx_dropped after processing LACPDUs
From: Jiri Bohac @ 2012-05-04 12:16 UTC (permalink / raw)
To: David Miller; +Cc: jbohac, eric.dumazet, fubar, andy, netdev
In-Reply-To: <20120502.194105.1211756092128572035.davem@davemloft.net>
On Wed, May 02, 2012 at 07:41:05PM -0400, David Miller wrote:
> I'm not going to go back to your original posting and put that
> commit message from there into the fixed patch. That's your
> job as a patch submitter, not mine.
Sorry! I'll resend...
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
^ permalink raw reply
* [PATCH v2] bonding: don't increase rx_dropped after processing LACPDUs
From: Jiri Bohac @ 2012-05-04 12:19 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, fubar, andy, netdev
In-Reply-To: <20120504121629.GB32665@midget.suse.cz>
Since commit 3aba891d, bonding processes LACP frames (802.3ad
mode) with bond_handle_frame(). Currently a copy of the skb is
made and the original is left to be processed by other
rx_handlers and the rest of the network stack by returning
RX_HANDLER_ANOTHER. As there is no protocol handler for
PKT_TYPE_LACPDU, the frame is dropped and dev->rx_dropped
increased.
Fix this by making bond_handle_frame() return RX_HANDLER_CONSUMED
if bonding has processed the LACP frame.
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2173,9 +2173,10 @@ re_arm:
* received frames (loopback). Since only the payload is given to this
* function, it check for loopback.
*/
-static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
{
struct port *port;
+ int ret = RX_HANDLER_ANOTHER;
if (length >= sizeof(struct lacpdu)) {
@@ -2184,11 +2185,12 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
if (!port->slave) {
pr_warning("%s: Warning: port of slave %s is uninitialized\n",
slave->dev->name, slave->dev->master->name);
- return;
+ return ret;
}
switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
+ ret = RX_HANDLER_CONSUMED;
pr_debug("Received LACPDU on port %d\n",
port->actor_port_number);
/* Protect against concurrent state machines */
@@ -2198,6 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
break;
case AD_TYPE_MARKER:
+ ret = RX_HANDLER_CONSUMED;
// No need to convert fields to Little Endian since we don't use the marker's fields.
switch (((struct bond_marker *)lacpdu)->tlv_type) {
@@ -2219,6 +2222,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
}
}
}
+ return ret;
}
/**
@@ -2456,18 +2460,20 @@ out:
return NETDEV_TX_OK;
}
-void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
+ int ret = RX_HANDLER_ANOTHER;
if (skb->protocol != PKT_TYPE_LACPDU)
- return;
+ return ret;
if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
- return;
+ return ret;
read_lock(&bond->lock);
- bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
+ ret = bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock);
+ return ret;
}
/*
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 235b2cc..5ee7e3c 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -274,7 +274,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 62d2409..0a0f4a6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1444,8 +1444,9 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct slave *slave;
struct bonding *bond;
- void (*recv_probe)(struct sk_buff *, struct bonding *,
+ int (*recv_probe)(struct sk_buff *, struct bonding *,
struct slave *);
+ int ret = RX_HANDLER_ANOTHER;
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
@@ -1464,8 +1465,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
if (likely(nskb)) {
- recv_probe(nskb, bond, slave);
+ ret = recv_probe(nskb, bond, slave);
dev_kfree_skb(nskb);
+ if (ret == RX_HANDLER_CONSUMED) {
+ kfree_skb(skb);
+ return ret;
+ }
}
}
@@ -1487,7 +1492,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
}
- return RX_HANDLER_ANOTHER;
+ return ret;
}
/* enslave device <slave> to bond device <master> */
@@ -2723,7 +2728,7 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
}
}
-static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
+static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
struct arphdr *arp;
@@ -2731,7 +2736,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
__be32 sip, tip;
if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
- return;
+ return RX_HANDLER_ANOTHER;
read_lock(&bond->lock);
@@ -2776,6 +2781,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
out_unlock:
read_unlock(&bond->lock);
+ return RX_HANDLER_ANOTHER;
}
/*
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
^ permalink raw reply related
* [PATCH 13/14] NET: MIPS: lantiq: implement OF support inside the etop driver
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, John Crispin, netdev
In-Reply-To: <1336133919-26525-1-git-send-email-blogic@openwrt.org>
This patch makes it possible to load the driver for the ETOP ethernet on
Lantiq SoC from a devicetree.
Additionally we convert the driver to using the new clkdev clock in favour of
the old ltq_pmu_*() api.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: netdev@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.
drivers/net/ethernet/lantiq_etop.c | 63 +++++++++++++++++++++++++++++------
1 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 5dc9cbd..c0443d4 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -29,19 +29,22 @@
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/mm.h>
-#include <linux/platform_device.h>
#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
#include <asm/checksum.h>
#include <lantiq_soc.h>
#include <xway_dma.h>
-#include <lantiq_platform.h>
#define LTQ_ETOP_MDIO 0x11804
#define MDIO_REQUEST 0x80000000
@@ -73,6 +76,7 @@
#define ETOP_CGEN 0x800
/* use 2 static channels for TX/RX */
+#define LTQ_DMA_CH0_INT INT_NUM_IM2_IRL0
#define LTQ_ETOP_TX_CHANNEL 1
#define LTQ_ETOP_RX_CHANNEL 6
#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
@@ -99,12 +103,17 @@ struct ltq_etop_chan {
struct ltq_etop_priv {
struct net_device *netdev;
struct platform_device *pdev;
- struct ltq_eth_data *pldata;
struct resource *res;
struct mii_bus *mii_bus;
struct phy_device *phydev;
+ struct clk *clk;
+ const void *mac;
+ int mii_mode;
+ int tx_irq;
+ int rx_irq;
+
struct ltq_etop_chan ch[MAX_DMA_CHAN];
int tx_free[MAX_DMA_CHAN >> 1];
@@ -239,7 +248,7 @@ ltq_etop_hw_exit(struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
int i;
- ltq_pmu_disable(PMU_PPE);
+ clk_disable(priv->clk);
for (i = 0; i < MAX_DMA_CHAN; i++)
if (IS_TX(i) || IS_RX(i))
ltq_etop_free_channel(dev, &priv->ch[i]);
@@ -251,9 +260,9 @@ ltq_etop_hw_init(struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
int i;
- ltq_pmu_enable(PMU_PPE);
+ clk_enable(priv->clk);
- switch (priv->pldata->mii_mode) {
+ switch (priv->mii_mode) {
case PHY_INTERFACE_MODE_RMII:
ltq_etop_w32_mask(ETOP_MII_MASK,
ETOP_MII_REVERSE, LTQ_ETOP_CFG);
@@ -266,7 +275,7 @@ ltq_etop_hw_init(struct net_device *dev)
default:
netdev_err(dev, "unknown mii mode %d\n",
- priv->pldata->mii_mode);
+ priv->mii_mode);
return -ENOTSUPP;
}
@@ -395,7 +404,7 @@ ltq_etop_mdio_probe(struct net_device *dev)
}
phydev = phy_connect(dev, dev_name(&phydev->dev), <q_etop_mdio_link,
- 0, priv->pldata->mii_mode);
+ 0, priv->mii_mode);
if (IS_ERR(phydev)) {
netdev_err(dev, "Could not attach to PHY\n");
@@ -643,7 +652,7 @@ ltq_etop_init(struct net_device *dev)
goto err_hw;
ltq_etop_change_mtu(dev, 1500);
- memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+ memcpy(&mac.sa_data, &priv->mac, ETH_ALEN);
if (!is_valid_ether_addr(mac.sa_data)) {
pr_warn("etop: invalid MAC, using random\n");
random_ether_addr(mac.sa_data);
@@ -707,9 +716,12 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
static int __init
ltq_etop_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
struct net_device *dev;
struct ltq_etop_priv *priv;
struct resource *res;
+ struct clk *clk;
+ struct resource irqres[2];
int err;
int i;
@@ -737,6 +749,20 @@ ltq_etop_probe(struct platform_device *pdev)
goto err_out;
}
+ err = of_irq_to_resource_table(node, irqres, 2);
+ if (err != 2) {
+ dev_err(&pdev->dev, "not enough irqs defined\n");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Failed to get clock\n");
+ err = PTR_ERR(clk);
+ goto err_out;
+ }
+
dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
if (!dev) {
err = -ENOMEM;
@@ -748,9 +774,15 @@ ltq_etop_probe(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->res = res;
priv->pdev = pdev;
- priv->pldata = dev_get_platdata(&pdev->dev);
priv->netdev = dev;
spin_lock_init(&priv->lock);
+ priv->tx_irq = irqres[0].start;
+ priv->rx_irq = irqres[1].start;
+ priv->mii_mode = of_get_phy_mode(node);
+ priv->mac = of_get_mac_address(node);
+ priv->clk = clk;
+ if (priv->mii_mode < 0)
+ priv->mii_mode = PHY_INTERFACE_MODE_MII;
for (i = 0; i < MAX_DMA_CHAN; i++) {
if (IS_TX(i))
@@ -779,21 +811,30 @@ static int __devexit
ltq_etop_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
+ struct ltq_etop_priv *priv = netdev_priv(dev);
if (dev) {
netif_tx_stop_all_queues(dev);
ltq_etop_hw_exit(dev);
ltq_etop_mdio_cleanup(dev);
+ clk_put(priv->clk);
unregister_netdev(dev);
}
return 0;
}
+static const struct of_device_id ltq_etop_match[] = {
+ { .compatible = "lantiq,etop-xway" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ltq_etop_match);
+
static struct platform_driver ltq_mii_driver = {
.remove = __devexit_p(ltq_etop_remove),
.driver = {
- .name = "ltq_etop",
+ .name = "etop-xway",
.owner = THIS_MODULE,
+ .of_match_table = ltq_etop_match,
},
};
--
1.7.9.1
^ permalink raw reply related
* Re: [PATCH net-next] net: skb_peek()/skb_peek_tail() cleanups
From: Eric Dumazet @ 2012-05-04 13:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120501.094127.190023878792795840.davem@davemloft.net>
On Tue, 2012-05-01 at 09:41 -0400, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 01 May 2012 04:31:46 +0200
>
> > From: Eric Dumazet <edumazet@google.com>
> >
> > remove useless casts and rename variables for less confusion.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
>
> Applied, I really need to get back to completing the list_head
> conversion :-/
Actually doubly linked lists everywhere has a performance issue.
When we dequeue one skb, we must bring in cpu cache the next skb as
well, to perform the unlink.
In some places it would be better to not have a double linked list, and
only perform a prefetch(skb->next).
^ permalink raw reply
* Re: [PATCH v2] bonding: don't increase rx_dropped after processing LACPDUs
From: Eric Dumazet @ 2012-05-04 13:04 UTC (permalink / raw)
To: Jiri Bohac; +Cc: David Miller, fubar, andy, netdev
In-Reply-To: <20120504121935.GC32665@midget.suse.cz>
On Fri, 2012-05-04 at 14:19 +0200, Jiri Bohac wrote:
> Since commit 3aba891d, bonding processes LACP frames (802.3ad
> mode) with bond_handle_frame(). Currently a copy of the skb is
> made and the original is left to be processed by other
> rx_handlers and the rest of the network stack by returning
> RX_HANDLER_ANOTHER. As there is no protocol handler for
> PKT_TYPE_LACPDU, the frame is dropped and dev->rx_dropped
> increased.
>
> Fix this by making bond_handle_frame() return RX_HANDLER_CONSUMED
> if bonding has processed the LACP frame.
>
> Signed-off-by: Jiri Bohac <jbohac@suse.cz>
>
> if (likely(nskb)) {
> - recv_probe(nskb, bond, slave);
> + ret = recv_probe(nskb, bond, slave);
> dev_kfree_skb(nskb);
> + if (ret == RX_HANDLER_CONSUMED) {
> + kfree_skb(skb);
consume_skb(skb) to not fool drop_monitor/dropwatch ?
> + return ret;
> + }
> }
> }
^ permalink raw reply
* Re: [PATCH v3] bonding: don't increase rx_dropped after processing LACPDUs
From: Jiri Bohac @ 2012-05-04 13:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Jiri Bohac, David Miller, fubar, andy, netdev
In-Reply-To: <1336136696.3752.320.camel@edumazet-glaptop>
On Fri, May 04, 2012 at 03:04:56PM +0200, Eric Dumazet wrote:
> On Fri, 2012-05-04 at 14:19 +0200, Jiri Bohac wrote:
> > if (likely(nskb)) {
> > - recv_probe(nskb, bond, slave);
> > + ret = recv_probe(nskb, bond, slave);
> > dev_kfree_skb(nskb);
> > + if (ret == RX_HANDLER_CONSUMED) {
> > + kfree_skb(skb);
>
> consume_skb(skb) to not fool drop_monitor/dropwatch ?
Thanks, fixed below:
Since commit 3aba891d, bonding processes LACP frames (802.3ad
mode) with bond_handle_frame(). Currently a copy of the skb is
made and the original is left to be processed by other
rx_handlers and the rest of the network stack by returning
RX_HANDLER_ANOTHER. As there is no protocol handler for
PKT_TYPE_LACPDU, the frame is dropped and dev->rx_dropped
increased.
Fix this by making bond_handle_frame() return RX_HANDLER_CONSUMED
if bonding has processed the LACP frame.
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2173,9 +2173,10 @@ re_arm:
* received frames (loopback). Since only the payload is given to this
* function, it check for loopback.
*/
-static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
{
struct port *port;
+ int ret = RX_HANDLER_ANOTHER;
if (length >= sizeof(struct lacpdu)) {
@@ -2184,11 +2185,12 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
if (!port->slave) {
pr_warning("%s: Warning: port of slave %s is uninitialized\n",
slave->dev->name, slave->dev->master->name);
- return;
+ return ret;
}
switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
+ ret = RX_HANDLER_CONSUMED;
pr_debug("Received LACPDU on port %d\n",
port->actor_port_number);
/* Protect against concurrent state machines */
@@ -2198,6 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
break;
case AD_TYPE_MARKER:
+ ret = RX_HANDLER_CONSUMED;
// No need to convert fields to Little Endian since we don't use the marker's fields.
switch (((struct bond_marker *)lacpdu)->tlv_type) {
@@ -2219,6 +2222,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
}
}
}
+ return ret;
}
/**
@@ -2456,18 +2460,20 @@ out:
return NETDEV_TX_OK;
}
-void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
+ int ret = RX_HANDLER_ANOTHER;
if (skb->protocol != PKT_TYPE_LACPDU)
- return;
+ return ret;
if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
- return;
+ return ret;
read_lock(&bond->lock);
- bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
+ ret = bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock);
+ return ret;
}
/*
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 235b2cc..5ee7e3c 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -274,7 +274,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 62d2409..0a0f4a6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1444,8 +1444,9 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct slave *slave;
struct bonding *bond;
- void (*recv_probe)(struct sk_buff *, struct bonding *,
+ int (*recv_probe)(struct sk_buff *, struct bonding *,
struct slave *);
+ int ret = RX_HANDLER_ANOTHER;
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
@@ -1464,8 +1465,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
if (likely(nskb)) {
- recv_probe(nskb, bond, slave);
+ ret = recv_probe(nskb, bond, slave);
dev_kfree_skb(nskb);
+ if (ret == RX_HANDLER_CONSUMED) {
+ consume_skb(skb);
+ return ret;
+ }
}
}
@@ -1487,7 +1492,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
}
- return RX_HANDLER_ANOTHER;
+ return ret;
}
/* enslave device <slave> to bond device <master> */
@@ -2723,7 +2728,7 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
}
}
-static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
+static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
struct arphdr *arp;
@@ -2731,7 +2736,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
__be32 sip, tip;
if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
- return;
+ return RX_HANDLER_ANOTHER;
read_lock(&bond->lock);
@@ -2776,6 +2781,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
out_unlock:
read_unlock(&bond->lock);
+ return RX_HANDLER_ANOTHER;
}
/*
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
^ permalink raw reply related
* RE: [PATCH] net: davinci_emac: Add pre_open, post_stop platform callbacks
From: Bedia, Vaibhav @ 2012-05-04 13:55 UTC (permalink / raw)
To: Hilman, Kevin, Ben Hutchings
Cc: Mark A. Greer, netdev@vger.kernel.org, linux-omap@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <87ehr1gdcv.fsf@ti.com>
Hi Kevin,
On Fri, May 04, 2012 at 03:02:16, Hilman, Kevin wrote:
> Ben Hutchings <bhutchings@solarflare.com> writes:
>
> > On Thu, 2012-05-03 at 19:25 +0000, Bedia, Vaibhav wrote:
> >> On Fri, May 04, 2012 at 00:16:32, Mark A. Greer wrote:
> >> [...]
> >> > >
> >> > > So, if I understood this correctly, it's effectively like blocking a low power
> >> > > state transition (here wfi execution) when EMAC is active?
> >> >
> >> > Assuming "it" is my patch, correct.
> >> >
> >>
> >> Recently I was thinking about how to get certain drivers to disallow some or all
> >> low power states and to me this also seems to fall in a similar category.
> >>
> >> One of the suggestions that I got was to check if the 'wakeup' entry associated with
> >> the device under sysfs could be leveraged for this. The PM code could maintain
> >> a whitelist (or blacklist) of devices and it decides the low power state to enter
> >> based on the 'wakeup' entries associated with these devices. In this particular case,
> >> maybe the driver could simply set this entry to non-wakeup capable when necessary and
> >> then let the PM code take care of skipping the wfi execution.
> >>
> >> Thoughts/brickbats welcome :)
> >
> > You can maybe (ab)use the pm_qos mechanism for this.
>
> I thought of using this too, but it doesn't actually solve the problem:
>
> Using PM QoS, you can avoid hitting the deeper idle states by setting a
> very low wakeup latency. However, on ARM platforms, even the shallowest
> idle states use the WFI instruction, and the EMAC would still not be
> able to wake the system from WFI. A possibility would be define the
> shallowest idle state to be one that doesn't call WFI and just does
> cpu_relax(). However, that would only work for CPUidle since PM QoS
> constraints are only checked by CPUidle. So, a non-CPUidle kernel would
> still have this bug. :(
>
> Ultimately, this is just broken HW. This network HW was bolted onto an
> existing SoC without consideration for wakeup capabilities. The result
> is that any use of this device with networking has to completely disable
> SoC power management.
>
I was checking with internally with some folks on the issue being addressed
in this patch and unfortunately no one seems to be aware of this :(
Mark mentioned nfs mounted rootfs being slow but in my limited testing I
didn't observe this on an AM3517 board. I am yet to go through the PSP code
to be fully sure that wfi instruction is indeed being executed but I wanted
to check if I need to do something specific to reproduce this at my end.
Irrespective of the above problem being present in the h/w, I feel the approach
of adding platform callbacks for blocking deeper idle states will create problems
when this is required for multiple peripherals. I agree that the default behavior
should be to support the deepest idle state based on the peripherals being used but
IMO the user should have the flexibility to change this behavior if he wishes
to do so.
I don't know whether the usage of the 'wakeup' entries for giving this
control to users qualifies as an abuse of the infrastructure. If it does, perhaps
there should some other mechanism for letting users control the system behavior.
Regards,
Vaibhav
^ permalink raw reply
* Re: [PATCH 04/15] drivers/net: Do not free an IRQ if its request failed
From: Lee Jones @ 2012-05-04 14:10 UTC (permalink / raw)
To: Lee Jones
Cc: linux-arm-kernel, arnd, linus.walleij, grant.likely, cjb, linux,
netdev
In-Reply-To: <1334867804-31942-5-git-send-email-lee.jones@linaro.org>
On 19/04/12 21:36, Lee Jones wrote:
> Refrain from attempting to free an interrupt line if the request
> fails and hence, there is no IRQ to free.
>
> CC: netdev@vger.kernel.org
> Signed-off-by: Lee Jones<lee.jones@linaro.org>
> ---
> drivers/net/ethernet/smsc/smsc911x.c | 3 +--
> 1 files changed, 1 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
> index 4a69710..f17a76e 100644
> --- a/drivers/net/ethernet/smsc/smsc911x.c
> +++ b/drivers/net/ethernet/smsc/smsc911x.c
> @@ -2382,7 +2382,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
> SET_NETDEV_DEV(dev,&pdev->dev);
>
> pdata = netdev_priv(dev);
> -
> dev->irq = irq_res->start;
> irq_flags = irq_res->flags& IRQF_TRIGGER_MASK;
> pdata->ioaddr = ioremap_nocache(res->start, res_size);
> @@ -2446,7 +2445,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
> if (retval) {
> SMSC_WARN(pdata, probe,
> "Unable to claim requested irq: %d", dev->irq);
> - goto out_free_irq;
> + goto out_disable_resources;
> }
>
> retval = register_netdev(dev);
Anything on this from the Net guys?
Kind regards,
Lee
--
Lee Jones
Linaro ST-Ericsson Landing Team Lead
M: +44 77 88 633 515
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCHv3 3/6] mISDN: L2 timeouts need to be queued as L2 event
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Karsten Keil <isdn@linux-pingi.de>
To be full preemptiv safe, we cannot handle a L2 timeout in the timer
context itself, we should do all actions via the D-channel thread.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/mISDN/layer2.c | 58 +++++++++++++++++++++++++++++++++++++++---
drivers/isdn/mISDN/tei.c | 13 +++++++--
include/linux/mISDNif.h | 7 ++++-
3 files changed, 69 insertions(+), 9 deletions(-)
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 39d7375..b6fbaec 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -58,6 +58,8 @@ enum {
EV_L1_DEACTIVATE,
EV_L2_T200,
EV_L2_T203,
+ EV_L2_T200I,
+ EV_L2_T203I,
EV_L2_SET_OWN_BUSY,
EV_L2_CLEAR_OWN_BUSY,
EV_L2_FRAME_ERROR,
@@ -86,6 +88,8 @@ static char *strL2Event[] =
"EV_L1_DEACTIVATE",
"EV_L2_T200",
"EV_L2_T203",
+ "EV_L2_T200I",
+ "EV_L2_T203I",
"EV_L2_SET_OWN_BUSY",
"EV_L2_CLEAR_OWN_BUSY",
"EV_L2_FRAME_ERROR",
@@ -276,6 +280,31 @@ ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) {
return ret;
}
+static void
+l2_timeout(struct FsmInst *fi, int event, void *arg)
+{
+ struct layer2 *l2 = fi->userdata;
+ struct sk_buff *skb;
+ struct mISDNhead *hh;
+
+ skb = mI_alloc_skb(0, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_WARNING "L2(%d,%d) nr:%x timer %s lost - no skb\n",
+ l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
+ "T200" : "T203");
+ return;
+ }
+ hh = mISDN_HEAD_P(skb);
+ hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND;
+ hh->id = l2->ch.nr;
+ if (*debug & DEBUG_TIMER)
+ printk(KERN_DEBUG "L2(%d,%d) nr:%x timer %s expired\n",
+ l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
+ "T200" : "T203");
+ if (l2->ch.st)
+ l2->ch.st->own.recv(&l2->ch.st->own, skb);
+}
+
static int
l2mgr(struct layer2 *l2, u_int prim, void *arg) {
long c = (long)arg;
@@ -1814,11 +1843,16 @@ static struct FsmNode L2FnList[] =
{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
{ST_L2_7, EV_L2_I, l2_got_iframe},
{ST_L2_8, EV_L2_I, l2_got_iframe},
- {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
- {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
- {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
- {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
- {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
+ {ST_L2_5, EV_L2_T200, l2_timeout},
+ {ST_L2_6, EV_L2_T200, l2_timeout},
+ {ST_L2_7, EV_L2_T200, l2_timeout},
+ {ST_L2_8, EV_L2_T200, l2_timeout},
+ {ST_L2_7, EV_L2_T203, l2_timeout},
+ {ST_L2_5, EV_L2_T200I, l2_st5_tout_200},
+ {ST_L2_6, EV_L2_T200I, l2_st6_tout_200},
+ {ST_L2_7, EV_L2_T200I, l2_st7_tout_200},
+ {ST_L2_8, EV_L2_T200I, l2_st8_tout_200},
+ {ST_L2_7, EV_L2_T203I, l2_st7_tout_203},
{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
@@ -1932,6 +1966,14 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
if (*debug & DEBUG_L2_RECV)
printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
__func__, hh->prim, hh->id, l2->sapi, l2->tei);
+ if (hh->prim == DL_INTERN_MSG) {
+ struct mISDNhead *chh = hh + 1; /* saved copy */
+
+ *hh = *chh;
+ if (*debug & DEBUG_L2_RECV)
+ printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n",
+ __func__, hh->prim, hh->id);
+ }
switch (hh->prim) {
case PH_DATA_IND:
ret = ph_data_indication(l2, hh, skb);
@@ -1987,6 +2029,12 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ,
skb);
break;
+ case DL_TIMER200_IND:
+ mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL);
+ break;
+ case DL_TIMER203_IND:
+ mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL);
+ break;
default:
if (*debug & DEBUG_L2)
l2m_debug(&l2->l2m, "l2 unknown pr %04x",
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 109276a..be88728 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -1294,7 +1294,7 @@ static int
mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
{
struct manager *mgr = container_of(ch, struct manager, bcast);
- struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ struct mISDNhead *hhc, *hh = mISDN_HEAD_P(skb);
struct sk_buff *cskb = NULL;
struct layer2 *l2;
u_long flags;
@@ -1309,10 +1309,17 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
skb = NULL;
} else {
if (!cskb)
- cskb = skb_copy(skb, GFP_KERNEL);
+ cskb = skb_copy(skb, GFP_ATOMIC);
}
if (cskb) {
- ret = l2->ch.send(&l2->ch, cskb);
+ hhc = mISDN_HEAD_P(cskb);
+ /* save original header behind normal header */
+ hhc++;
+ *hhc = *hh;
+ hhc--;
+ hhc->prim = DL_INTERN_MSG;
+ hhc->id = l2->ch.nr;
+ ret = ch->st->own.recv(&ch->st->own, cskb);
if (ret) {
if (*debug & DEBUG_SEND_ERR)
printk(KERN_DEBUG
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b5e7f22..b80f764 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
*/
#define MISDN_MAJOR_VERSION 1
#define MISDN_MINOR_VERSION 1
-#define MISDN_RELEASE 21
+#define MISDN_RELEASE 26
/* primitives for information exchange
* generell format
@@ -115,6 +115,11 @@
#define MDL_ERROR_IND 0x1F04
#define MDL_ERROR_RSP 0x5F04
+/* intern layer 2 */
+#define DL_TIMER200_IND 0x7004
+#define DL_TIMER203_IND 0x7304
+#define DL_INTERN_MSG 0x7804
+
/* DL_INFORMATION_IND types */
#define DL_INFO_L2_CONNECT 0x0001
#define DL_INFO_L2_REMOVED 0x0002
--
1.7.3.4
^ permalink raw reply related
* [PATCHv3 6/6] mISDN: Help to identify the card
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Karsten Keil <isdn@linux-pingi.de>
With multiple cards is hard to figure out which port caused trouble
int the layer2 routines (e.g. got a timeout).
Now we have the informations in the log output.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/mISDN/core.c | 16 +++++++++
drivers/isdn/mISDN/layer2.c | 76 +++++++++++++++++++++++++------------------
include/linux/mISDNif.h | 3 +-
3 files changed, 62 insertions(+), 33 deletions(-)
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index a24530f..c401634 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -355,6 +355,22 @@ mISDN_unregister_Bprotocol(struct Bprotocol *bp)
}
EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
+static const char *msg_no_channel = "<no channel>";
+static const char *msg_no_stack = "<no stack>";
+static const char *msg_no_stackdev = "<no stack device>";
+
+const char *mISDNDevName4ch(struct mISDNchannel *ch)
+{
+ if (!ch)
+ return msg_no_channel;
+ if (!ch->st)
+ return msg_no_stack;
+ if (!ch->st->dev)
+ return msg_no_stackdev;
+ return dev_name(&ch->st->dev->dev);
+};
+EXPORT_SYMBOL(mISDNDevName4ch);
+
static int
mISDNInit(void)
{
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index b6fbaec..0dc8abc 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -110,8 +110,8 @@ l2m_debug(struct FsmInst *fi, char *fmt, ...)
vaf.fmt = fmt;
vaf.va = &va;
- printk(KERN_DEBUG "l2 (sapi %d tei %d): %pV\n",
- l2->sapi, l2->tei, &vaf);
+ printk(KERN_DEBUG "%s l2 (sapi %d tei %d): %pV\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, &vaf);
va_end(va);
}
@@ -154,7 +154,8 @@ l2up(struct layer2 *l2, u_int prim, struct sk_buff *skb)
mISDN_HEAD_ID(skb) = (l2->ch.nr << 16) | l2->ch.addr;
err = l2->up->send(l2->up, skb);
if (err) {
- printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+ printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
+ mISDNDevName4ch(&l2->ch), err);
dev_kfree_skb(skb);
}
}
@@ -178,7 +179,8 @@ l2up_create(struct layer2 *l2, u_int prim, int len, void *arg)
memcpy(skb_put(skb, len), arg, len);
err = l2->up->send(l2->up, skb);
if (err) {
- printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+ printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
+ mISDNDevName4ch(&l2->ch), err);
dev_kfree_skb(skb);
}
}
@@ -189,7 +191,8 @@ l2down_skb(struct layer2 *l2, struct sk_buff *skb) {
ret = l2->ch.recv(l2->ch.peer, skb);
if (ret && (*debug & DEBUG_L2_RECV))
- printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
+ printk(KERN_DEBUG "l2down_skb: dev %s ret(%d)\n",
+ mISDNDevName4ch(&l2->ch), ret);
return ret;
}
@@ -289,18 +292,18 @@ l2_timeout(struct FsmInst *fi, int event, void *arg)
skb = mI_alloc_skb(0, GFP_ATOMIC);
if (!skb) {
- printk(KERN_WARNING "L2(%d,%d) nr:%x timer %s lost - no skb\n",
- l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
- "T200" : "T203");
+ printk(KERN_WARNING "%s: L2(%d,%d) nr:%x timer %s no skb\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
+ l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
return;
}
hh = mISDN_HEAD_P(skb);
hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND;
hh->id = l2->ch.nr;
if (*debug & DEBUG_TIMER)
- printk(KERN_DEBUG "L2(%d,%d) nr:%x timer %s expired\n",
- l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
- "T200" : "T203");
+ printk(KERN_DEBUG "%s: L2(%d,%d) nr:%x timer %s expired\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
+ l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
if (l2->ch.st)
l2->ch.st->own.recv(&l2->ch.st->own, skb);
}
@@ -309,8 +312,8 @@ static int
l2mgr(struct layer2 *l2, u_int prim, void *arg) {
long c = (long)arg;
- printk(KERN_WARNING
- "l2mgr: addr:%x prim %x %c\n", l2->id, prim, (char)c);
+ printk(KERN_WARNING "l2mgr: dev %s addr:%x prim %x %c\n",
+ mISDNDevName4ch(&l2->ch), l2->id, prim, (char)c);
if (test_bit(FLG_LAPD, &l2->flag) &&
!test_bit(FLG_FIXED_TEI, &l2->flag)) {
switch (c) {
@@ -632,8 +635,8 @@ send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr)
else {
skb = mI_alloc_skb(i, GFP_ATOMIC);
if (!skb) {
- printk(KERN_WARNING "%s: can't alloc skbuff\n",
- __func__);
+ printk(KERN_WARNING "%s: can't alloc skbuff in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
}
@@ -1118,8 +1121,8 @@ enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf)
tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
skb = mI_alloc_skb(i, GFP_ATOMIC);
if (!skb) {
- printk(KERN_WARNING
- "isdnl2 can't alloc sbbuff for enquiry_cr\n");
+ printk(KERN_WARNING "%s: isdnl2 can't alloc sbbuff in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
memcpy(skb_put(skb, i), tmp, i);
@@ -1179,7 +1182,7 @@ invoke_retransmission(struct layer2 *l2, unsigned int nr)
else
printk(KERN_WARNING
"%s: windowar[%d] is NULL\n",
- __func__, p1);
+ mISDNDevName4ch(&l2->ch), p1);
l2->windowar[p1] = NULL;
}
mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
@@ -1490,8 +1493,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
p1 = (l2->vs - l2->va) % 8;
p1 = (p1 + l2->sow) % l2->window;
if (l2->windowar[p1]) {
- printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
- p1);
+ printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
+ mISDNDevName4ch(&l2->ch), p1);
dev_kfree_skb(l2->windowar[p1]);
}
l2->windowar[p1] = skb;
@@ -1511,12 +1514,14 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
memcpy(skb_push(nskb, i), header, i);
else {
printk(KERN_WARNING
- "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
+ "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
+ mISDNDevName4ch(&l2->ch), i, p1);
oskb = nskb;
nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
if (!nskb) {
dev_kfree_skb(oskb);
- printk(KERN_WARNING "%s: no skb mem\n", __func__);
+ printk(KERN_WARNING "%s: no skb mem in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
memcpy(skb_put(nskb, i), header, i);
@@ -1892,7 +1897,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
ptei = *datap++;
if ((psapi & 1) || !(ptei & 1)) {
printk(KERN_WARNING
- "l2 D-channel frame wrong EA0/EA1\n");
+ "%s l2 D-channel frame wrong EA0/EA1\n",
+ mISDNDevName4ch(&l2->ch));
return ret;
}
psapi >>= 2;
@@ -1901,7 +1907,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
/* not our business */
if (*debug & DEBUG_L2)
printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n",
- __func__, psapi, l2->sapi);
+ mISDNDevName4ch(&l2->ch), psapi,
+ l2->sapi);
dev_kfree_skb(skb);
return 0;
}
@@ -1909,7 +1916,7 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
/* not our business */
if (*debug & DEBUG_L2)
printk(KERN_DEBUG "%s: tei %d/%d mismatch\n",
- __func__, ptei, l2->tei);
+ mISDNDevName4ch(&l2->ch), ptei, l2->tei);
dev_kfree_skb(skb);
return 0;
}
@@ -1950,7 +1957,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
} else
c = 'L';
if (c) {
- printk(KERN_WARNING "l2 D-channel frame error %c\n", c);
+ printk(KERN_WARNING "%s:l2 D-channel frame error %c\n",
+ mISDNDevName4ch(&l2->ch), c);
mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
}
return ret;
@@ -1964,15 +1972,16 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
int ret = -EINVAL;
if (*debug & DEBUG_L2_RECV)
- printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
- __func__, hh->prim, hh->id, l2->sapi, l2->tei);
+ printk(KERN_DEBUG "%s: %s prim(%x) id(%x) sapi(%d) tei(%d)\n",
+ __func__, mISDNDevName4ch(&l2->ch), hh->prim, hh->id,
+ l2->sapi, l2->tei);
if (hh->prim == DL_INTERN_MSG) {
struct mISDNhead *chh = hh + 1; /* saved copy */
*hh = *chh;
if (*debug & DEBUG_L2_RECV)
printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n",
- __func__, hh->prim, hh->id);
+ mISDNDevName4ch(&l2->ch), hh->prim, hh->id);
}
switch (hh->prim) {
case PH_DATA_IND:
@@ -2053,7 +2062,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
int ret = -EINVAL;
if (*debug & DEBUG_L2_TEI)
- printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
+ printk(KERN_DEBUG "%s: cmd(%x) in %s\n",
+ mISDNDevName4ch(&l2->ch), cmd, __func__);
switch (cmd) {
case (MDL_ASSIGN_REQ):
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, (void *)arg);
@@ -2066,7 +2076,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
break;
case (MDL_ERROR_RSP):
/* ETS 300-125 5.3.2.1 Test: TC13010 */
- printk(KERN_NOTICE "MDL_ERROR|REQ (tei_l2)\n");
+ printk(KERN_NOTICE "%s: MDL_ERROR|REQ (tei_l2)\n",
+ mISDNDevName4ch(&l2->ch));
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL);
break;
}
@@ -2098,7 +2109,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
u_int info;
if (*debug & DEBUG_L2_CTRL)
- printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
+ printk(KERN_DEBUG "%s: %s cmd(%x)\n",
+ mISDNDevName4ch(ch), __func__, cmd);
switch (cmd) {
case OPEN_CHANNEL:
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index 9cc8ce5..ce6e613 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
*/
#define MISDN_MAJOR_VERSION 1
#define MISDN_MINOR_VERSION 1
-#define MISDN_RELEASE 27
+#define MISDN_RELEASE 28
/* primitives for information exchange
* generell format
@@ -591,6 +591,7 @@ static inline struct mISDNdevice *dev_to_mISDN(struct device *dev)
extern void set_channel_address(struct mISDNchannel *, u_int, u_int);
extern void mISDN_clock_update(struct mISDNclock *, int, struct timeval *);
extern unsigned short mISDN_clock_get(void);
+extern const char *mISDNDevName4ch(struct mISDNchannel *);
#endif /* __KERNEL__ */
#endif /* mISDNIF_H */
--
1.7.3.4
^ permalink raw reply related
* [PATCHv3 1/6] mISDN: Added PH_* state info to tei manager.
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Andreas Eversberg, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Andreas Eversberg <andreas@eversberg.eu>
Tei manager reports current layer 1 state on creation.
On state change it reports it to the socket interface.
Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/mISDN/tei.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index ba2bc0c..969766f 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -1023,6 +1023,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
mgr->up = crq->ch;
id = DL_INFO_L2_CONNECT;
teiup_create(mgr, DL_INFORMATION_IND, sizeof(id), &id);
+ if (test_bit(MGR_PH_ACTIVE, &mgr->options))
+ teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
crq->ch = NULL;
if (!list_empty(&mgr->layer2)) {
read_lock_irqsave(&mgr->lock, flags);
@@ -1096,12 +1098,16 @@ mgr_send(struct mISDNchannel *ch, struct sk_buff *skb)
break;
case PH_ACTIVATE_IND:
test_and_set_bit(MGR_PH_ACTIVE, &mgr->options);
+ if (mgr->up)
+ teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
mISDN_FsmEvent(&mgr->deact, EV_ACTIVATE_IND, NULL);
do_send(mgr);
ret = 0;
break;
case PH_DEACTIVATE_IND:
test_and_clear_bit(MGR_PH_ACTIVE, &mgr->options);
+ if (mgr->up)
+ teiup_create(mgr, PH_DEACTIVATE_IND, 0, NULL);
mISDN_FsmEvent(&mgr->deact, EV_DEACTIVATE_IND, NULL);
ret = 0;
break;
--
1.7.3.4
^ permalink raw reply related
* [PATCHv3 0/6] mISDN: Collection of patches for layer1/layer2
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Version 3
Implement the TIMER3 configuration in one patch.
Fix additional issues found by checkpatch --strict
Version 2
I removed the PCM only stuff and the 2MBit test mode and will rework
them for a later submit. I added the lowlevel driver changes for the TIMER3
config to this series.
These patches are mainly the outcome of a TBR3 recertification done
within BT labs.
The patches itself are very well tested more as 10000 valid/invalid
call setup were done in preparartion for the TBR3 aproval.
For net-next.
Andreas Eversberg (1):
mISDN: Added PH_* state info to tei manager.
Karsten Keil (5):
mISDN: Fix refcounting bug
mISDN: L2 timeouts need to be queued as L2 event
mISDN: Make layer1 timer 3 value configurable
mISDN: Layer1 statemachine fix
mISDN: Help to identify the card
drivers/isdn/hardware/mISDN/avmfritz.c | 5 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 5 +-
drivers/isdn/hardware/mISDN/hfcpci.c | 5 +-
drivers/isdn/hardware/mISDN/mISDNipac.c | 17 +++--
drivers/isdn/hardware/mISDN/netjet.c | 5 +-
drivers/isdn/hardware/mISDN/speedfax.c | 5 +-
drivers/isdn/hardware/mISDN/w6692.c | 5 +-
drivers/isdn/mISDN/core.c | 16 ++++
drivers/isdn/mISDN/layer1.c | 36 +++++++---
drivers/isdn/mISDN/layer2.c | 120 +++++++++++++++++++++++--------
drivers/isdn/mISDN/tei.c | 72 ++++++++++++++-----
include/linux/mISDNhw.h | 3 +
include/linux/mISDNif.h | 9 ++-
13 files changed, 234 insertions(+), 69 deletions(-)
--
1.7.3.4
^ permalink raw reply
* [PATCHv3 2/6] mISDN: Fix refcounting bug
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Karsten Keil, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Karsten Keil <isdn@linux-pingi.de>
Under some configs it was still not possible to unload the driver,
because the module use count was srewed up.
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/mISDN/tei.c | 53 +++++++++++++++++++++++++++++++++------------
1 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 969766f..109276a 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -790,18 +790,23 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
static struct layer2 *
create_new_tei(struct manager *mgr, int tei, int sapi)
{
- u_long opt = 0;
- u_long flags;
- int id;
- struct layer2 *l2;
+ unsigned long opt = 0;
+ unsigned long flags;
+ int id;
+ struct layer2 *l2;
+ struct channel_req rq;
if (!mgr->up)
return NULL;
if ((tei >= 0) && (tei < 64))
test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
- if (mgr->ch.st->dev->Dprotocols
- & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
+ if (mgr->ch.st->dev->Dprotocols & ((1 << ISDN_P_TE_E1) |
+ (1 << ISDN_P_NT_E1))) {
test_and_set_bit(OPTION_L2_PMX, &opt);
+ rq.protocol = ISDN_P_NT_E1;
+ } else {
+ rq.protocol = ISDN_P_NT_S0;
+ }
l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
if (!l2) {
printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
@@ -836,6 +841,14 @@ create_new_tei(struct manager *mgr, int tei, int sapi)
l2->ch.recv = mgr->ch.recv;
l2->ch.peer = mgr->ch.peer;
l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
+ /* We need open here L1 for the manager as well (refcounting) */
+ rq.adr.dev = mgr->ch.st->dev->id;
+ id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL, &rq);
+ if (id < 0) {
+ printk(KERN_WARNING "%s: cannot open L1\n", __func__);
+ l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+ l2 = NULL;
+ }
}
return l2;
}
@@ -978,10 +991,11 @@ TEIrelease(struct layer2 *l2)
static int
create_teimgr(struct manager *mgr, struct channel_req *crq)
{
- struct layer2 *l2;
- u_long opt = 0;
- u_long flags;
- int id;
+ struct layer2 *l2;
+ unsigned long opt = 0;
+ unsigned long flags;
+ int id;
+ struct channel_req l1rq;
if (*debug & DEBUG_L2_TEI)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
@@ -1016,6 +1030,7 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
if (crq->protocol == ISDN_P_LAPD_TE)
test_and_set_bit(MGR_OPT_USER, &mgr->options);
}
+ l1rq.adr = crq->adr;
if (mgr->ch.st->dev->Dprotocols
& ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
test_and_set_bit(OPTION_L2_PMX, &opt);
@@ -1055,24 +1070,34 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
l2->tm->tei_m.fsm = &teifsmu;
l2->tm->tei_m.state = ST_TEI_NOP;
l2->tm->tval = 1000; /* T201 1 sec */
+ if (test_bit(OPTION_L2_PMX, &opt))
+ l1rq.protocol = ISDN_P_TE_E1;
+ else
+ l1rq.protocol = ISDN_P_TE_S0;
} else {
l2->tm->tei_m.fsm = &teifsmn;
l2->tm->tei_m.state = ST_TEI_NOP;
l2->tm->tval = 2000; /* T202 2 sec */
+ if (test_bit(OPTION_L2_PMX, &opt))
+ l1rq.protocol = ISDN_P_NT_E1;
+ else
+ l1rq.protocol = ISDN_P_NT_S0;
}
mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
write_lock_irqsave(&mgr->lock, flags);
id = get_free_id(mgr);
list_add_tail(&l2->list, &mgr->layer2);
write_unlock_irqrestore(&mgr->lock, flags);
- if (id < 0) {
- l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
- } else {
+ if (id >= 0) {
l2->ch.nr = id;
l2->up->nr = id;
crq->ch = &l2->ch;
- id = 0;
+ /* We need open here L1 for the manager as well (refcounting) */
+ id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL,
+ &l1rq);
}
+ if (id < 0)
+ l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
return id;
}
--
1.7.3.4
^ permalink raw reply related
* [PATCHv3 4/6] mISDN: Make layer1 timer 3 value configurable
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Karsten Keil <isdn@linux-pingi.de>
For certification test it is very useful to change the layer1
timer3 value on runtime.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/hardware/mISDN/avmfritz.c | 5 ++++-
drivers/isdn/hardware/mISDN/hfcmulti.c | 5 ++++-
drivers/isdn/hardware/mISDN/hfcpci.c | 5 ++++-
drivers/isdn/hardware/mISDN/mISDNipac.c | 17 ++++++++++++-----
drivers/isdn/hardware/mISDN/netjet.c | 5 ++++-
drivers/isdn/hardware/mISDN/speedfax.c | 5 ++++-
drivers/isdn/hardware/mISDN/w6692.c | 5 ++++-
drivers/isdn/mISDN/layer1.c | 16 ++++++++++++++--
include/linux/mISDNhw.h | 3 +++
include/linux/mISDNif.h | 3 ++-
10 files changed, 55 insertions(+), 14 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index c0b8c96..6bf2c58 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -868,7 +868,7 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -878,6 +878,9 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
}
ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = fc->isac.ctrl(&fc->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
ret = -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 4301331..4c128e4 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -4161,7 +4161,7 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_HFC_OP;
+ cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_HFC_WD_INIT: /* init the watchdog */
wd_cnt = cq->p1 & 0xf;
@@ -4191,6 +4191,9 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
__func__);
HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(dch->l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
+ break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n",
__func__, cq->op);
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index e2c83a2..5fe993e 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -1819,7 +1819,7 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_CONNECT |
- MISDN_CTRL_DISCONNECT;
+ MISDN_CTRL_DISCONNECT | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* channel 0 disabled loop */
@@ -1896,6 +1896,9 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
hc->hw.trm &= 0x7f; /* disable IOM-loop */
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(hc->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
+ break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n",
__func__, cq->op);
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 884369f..92d4a78 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -603,10 +603,11 @@ isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
}
static int
-isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
+isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
{
u8 tl = 0;
- u_long flags;
+ unsigned long flags;
+ int ret = 0;
switch (cmd) {
case HW_TESTLOOP:
@@ -626,12 +627,15 @@ isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
}
spin_unlock_irqrestore(isac->hwlock, flags);
break;
+ case HW_TIMER3_VALUE:
+ ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
+ break;
default:
pr_debug("%s: %s unknown command %x %lx\n", isac->name,
__func__, cmd, para);
- return -1;
+ ret = -1;
}
- return 0;
+ return ret;
}
static int
@@ -1526,7 +1530,7 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -1536,6 +1540,9 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
}
ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
ret = -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index c726e09..27998d7 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -837,7 +837,7 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -847,6 +847,9 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
}
ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = card->isac.ctrl(&card->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
ret = -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 0468993..93f344d 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -224,7 +224,7 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -234,6 +234,9 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
}
ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = sf->isac.ctrl(&sf->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: unknown Op %x\n", sf->name, cq->op);
ret = -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 2183357..1d04467 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -1035,7 +1035,10 @@ channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = 0;
+ cq->op = MISDN_CTRL_L1_TIMER3;
+ break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(card->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
break;
default:
pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op);
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index 0fc49b3..ff05153 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -30,11 +30,12 @@ struct layer1 {
struct FsmInst l1m;
struct FsmTimer timer;
int delay;
+ int t3_value;
struct dchannel *dch;
dchannel_l1callback *dcb;
};
-#define TIMER3_VALUE 7000
+#define TIMER3_DEFAULT_VALUE 7000
static
struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};
@@ -233,7 +234,7 @@ l1_activate_s(struct FsmInst *fi, int event, void *arg)
{
struct layer1 *l1 = fi->userdata;
- mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+ mISDN_FsmRestartTimer(&l1->timer, l1->t3_value, EV_TIMER3, NULL, 2);
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
l1->dcb(l1->dch, HW_RESET_REQ);
}
@@ -356,6 +357,16 @@ l1_event(struct layer1 *l1, u_int event)
release_l1(l1);
break;
default:
+ if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {
+ int val = event & HW_TIMER3_VMASK;
+
+ if (val < 5)
+ val = 5;
+ if (val > 30)
+ val = 30;
+ l1->t3_value = val;
+ break;
+ }
if (*debug & DEBUG_L1)
printk(KERN_DEBUG "%s %x unhandled\n",
__func__, event);
@@ -377,6 +388,7 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
nl1->l1m.fsm = &l1fsm_s;
nl1->l1m.state = ST_L1_F3;
nl1->Flags = 0;
+ nl1->t3_value = TIMER3_DEFAULT_VALUE;
nl1->l1m.debug = *debug & DEBUG_L1_FSM;
nl1->l1m.userdata = nl1;
nl1->l1m.userint = 0;
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 4af8414..de165b5 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -135,6 +135,9 @@ extern int create_l1(struct dchannel *, dchannel_l1callback *);
#define HW_TESTRX_RAW 0x9602
#define HW_TESTRX_HDLC 0x9702
#define HW_TESTRX_OFF 0x9802
+#define HW_TIMER3_IND 0x9902
+#define HW_TIMER3_VALUE 0x9a00
+#define HW_TIMER3_VMASK 0x00FF
struct layer1;
extern int l1_event(struct layer1 *, u_int);
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b80f764..9cc8ce5 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
*/
#define MISDN_MAJOR_VERSION 1
#define MISDN_MINOR_VERSION 1
-#define MISDN_RELEASE 26
+#define MISDN_RELEASE 27
/* primitives for information exchange
* generell format
@@ -372,6 +372,7 @@ clear_channelmap(u_int nr, u_char *map)
#define MISDN_CTRL_RX_OFF 0x0100
#define MISDN_CTRL_FILL_EMPTY 0x0200
#define MISDN_CTRL_GETPEER 0x0400
+#define MISDN_CTRL_L1_TIMER3 0x0800
#define MISDN_CTRL_HW_FEATURES_OP 0x2000
#define MISDN_CTRL_HW_FEATURES 0x2001
#define MISDN_CTRL_HFC_OP 0x4000
--
1.7.3.4
^ permalink raw reply related
* [PATCHv3 5/6] mISDN: Layer1 statemachine fix
From: Karsten Keil @ 2012-05-04 14:15 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Karsten Keil
In-Reply-To: <1336140935-25830-1-git-send-email-kkeil@linux-pingi.de>
From: Karsten Keil <isdn@linux-pingi.de>
The timer3 and the activation delay timer need to be independent.
If timer3 fires do not reqest power up we have to send only INFO 0.
Now layer1 pass TBR3 again.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/mISDN/layer1.c | 22 +++++++++++++---------
1 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index ff05153..bebc57b 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -28,7 +28,8 @@ static u_int *debug;
struct layer1 {
u_long Flags;
struct FsmInst l1m;
- struct FsmTimer timer;
+ struct FsmTimer timer3;
+ struct FsmTimer timerX;
int delay;
int t3_value;
struct dchannel *dch;
@@ -135,7 +136,7 @@ l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
struct layer1 *l1 = fi->userdata;
mISDN_FsmChangeState(fi, ST_L1_F3);
- mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
+ mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);
test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
}
@@ -180,11 +181,11 @@ l1_info4_ind(struct FsmInst *fi, int event, void *arg)
mISDN_FsmChangeState(fi, ST_L1_F7);
l1->dcb(l1->dch, INFO3_P8);
if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
- mISDN_FsmDelTimer(&l1->timer, 4);
+ mISDN_FsmDelTimer(&l1->timerX, 4);
if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
- mISDN_FsmDelTimer(&l1->timer, 3);
- mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
+ mISDN_FsmDelTimer(&l1->timer3, 3);
+ mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);
test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
}
}
@@ -202,7 +203,7 @@ l1_timer3(struct FsmInst *fi, int event, void *arg)
}
if (l1->l1m.state != ST_L1_F6) {
mISDN_FsmChangeState(fi, ST_L1_F3);
- l1->dcb(l1->dch, HW_POWERUP_REQ);
+ /* do not force anything here, we need send INFO 0 */
}
}
@@ -234,8 +235,9 @@ l1_activate_s(struct FsmInst *fi, int event, void *arg)
{
struct layer1 *l1 = fi->userdata;
- mISDN_FsmRestartTimer(&l1->timer, l1->t3_value, EV_TIMER3, NULL, 2);
+ mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
+ /* Tell HW to send INFO 1 */
l1->dcb(l1->dch, HW_RESET_REQ);
}
@@ -303,7 +305,8 @@ static struct FsmNode L1SFnList[] =
static void
release_l1(struct layer1 *l1) {
- mISDN_FsmDelTimer(&l1->timer, 0);
+ mISDN_FsmDelTimer(&l1->timerX, 0);
+ mISDN_FsmDelTimer(&l1->timer3, 0);
if (l1->dch)
l1->dch->l1 = NULL;
module_put(THIS_MODULE);
@@ -395,7 +398,8 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
nl1->l1m.printdebug = l1m_debug;
nl1->dch = dch;
nl1->dcb = dcb;
- mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
+ mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);
+ mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);
__module_get(THIS_MODULE);
dch->l1 = nl1;
return 0;
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH] net: davinci_emac: Add pre_open, post_stop platform callbacks
From: Kevin Hilman @ 2012-05-04 14:31 UTC (permalink / raw)
To: Bedia, Vaibhav, nsekhar
Cc: Ben Hutchings, Mark A. Greer, netdev@vger.kernel.org,
linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org
In-Reply-To: <B5906170F1614E41A8A28DE3B8D121433EA81B04@DBDE01.ent.ti.com>
+Sekhar
"Bedia, Vaibhav" <vaibhav.bedia@ti.com> writes:
> Hi Kevin,
>
> On Fri, May 04, 2012 at 03:02:16, Hilman, Kevin wrote:
>> Ben Hutchings <bhutchings@solarflare.com> writes:
>>
>> > On Thu, 2012-05-03 at 19:25 +0000, Bedia, Vaibhav wrote:
>> >> On Fri, May 04, 2012 at 00:16:32, Mark A. Greer wrote:
>> >> [...]
>> >> > >
>> >> > > So, if I understood this correctly, it's effectively like blocking a low power
>> >> > > state transition (here wfi execution) when EMAC is active?
>> >> >
>> >> > Assuming "it" is my patch, correct.
>> >> >
>> >>
>> >> Recently I was thinking about how to get certain drivers to disallow some or all
>> >> low power states and to me this also seems to fall in a similar category.
>> >>
>> >> One of the suggestions that I got was to check if the 'wakeup' entry associated with
>> >> the device under sysfs could be leveraged for this. The PM code could maintain
>> >> a whitelist (or blacklist) of devices and it decides the low power state to enter
>> >> based on the 'wakeup' entries associated with these devices. In this particular case,
>> >> maybe the driver could simply set this entry to non-wakeup capable when necessary and
>> >> then let the PM code take care of skipping the wfi execution.
>> >>
>> >> Thoughts/brickbats welcome :)
>> >
>> > You can maybe (ab)use the pm_qos mechanism for this.
>>
>> I thought of using this too, but it doesn't actually solve the problem:
>>
>> Using PM QoS, you can avoid hitting the deeper idle states by setting a
>> very low wakeup latency. However, on ARM platforms, even the shallowest
>> idle states use the WFI instruction, and the EMAC would still not be
>> able to wake the system from WFI. A possibility would be define the
>> shallowest idle state to be one that doesn't call WFI and just does
>> cpu_relax(). However, that would only work for CPUidle since PM QoS
>> constraints are only checked by CPUidle. So, a non-CPUidle kernel would
>> still have this bug. :(
>>
>> Ultimately, this is just broken HW. This network HW was bolted onto an
>> existing SoC without consideration for wakeup capabilities. The result
>> is that any use of this device with networking has to completely disable
>> SoC power management.
>>
>
> I was checking with internally with some folks on the issue being addressed
> in this patch and unfortunately no one seems to be aware of this :(
Do you mean they are not aware that the EMAC cannot wakeup th SoC, or
they are not aware that having a device that cannot wakup the SoC has
such an impact on Linux.
> Mark mentioned nfs mounted rootfs being slow but in my limited testing I
> didn't observe this on an AM3517 board. I am yet to go through the PSP code
> to be fully sure that wfi instruction is indeed being executed but I wanted
> to check if I need to do something specific to reproduce this at my end.
Based on my discussion with Mark, I suspect that the kernel you're using
is simply not going idle.
> Irrespective of the above problem being present in the h/w, I feel the approach
> of adding platform callbacks for blocking deeper idle states will create problems
> when this is required for multiple peripherals.
I agree. If we have to do this for multiple peripherals, the curren
approach it will become unwieldy.
> I agree that the default behavior should be to support the deepest
> idle state based on the peripherals being used but IMO the user should
> have the flexibility to change this behavior if he wishes to do so.
Well, we always have the option of booting with 'nohlt' on the
commandline.
Since nobody seems to have thought about idle power management in the HW
design, maybe we shouldn't break our backs to hack around the
HW brokenness.
Personally, I'm perfectly OK leaving the default behavior of
sluggish/unresponsive devices that are not wakeup capable. The only fix
is to not sleep, and that can be accomplished on the cmdline using
nohlt (at the expense of some energy savings.)
> I don't know whether the usage of the 'wakeup' entries for giving this
> control to users qualifies as an abuse of the infrastructure.
It does.
> If it does, perhaps there should some other mechanism for letting
> users control the system behavior.
Come to think of it, the right solution here is probably to use runtime
PM. We could then to add some custom hooks for davinci_emac in the
device code to use enable_hlt/disable_hlt based on activity.
In order to do that though, the davinci_emac driver needs to be runtime
PM converted.
Kevin
^ permalink raw reply
* [PATCH net-next] net: sched: factorize code (qdisc_drop())
From: Eric Dumazet @ 2012-05-04 14:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
Use qdisc_drop() helper where possible.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/sched/sch_choke.c | 8 +++-----
net/sched/sch_dsmark.c | 3 +--
net/sched/sch_htb.c | 4 +---
net/sched/sch_teql.c | 4 +---
4 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 81445cc..cc37dd5 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -332,15 +332,13 @@ static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch)
}
q->stats.pdrop++;
- sch->qstats.drops++;
- kfree_skb(skb);
- return NET_XMIT_DROP;
+ return qdisc_drop(skb, sch);
- congestion_drop:
+congestion_drop:
qdisc_drop(skb, sch);
return NET_XMIT_CN;
- other_drop:
+other_drop:
if (ret & __NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb(skb);
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 389b856..3886365 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -265,8 +265,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_SUCCESS;
drop:
- kfree_skb(skb);
- sch->qstats.drops++;
+ qdisc_drop(skb, sch);
return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
}
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 2ea6f19..acae5b0 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -558,9 +558,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
__skb_queue_tail(&q->direct_queue, skb);
q->direct_pkts++;
} else {
- kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_DROP;
+ return qdisc_drop(skb, sch);
}
#ifdef CONFIG_NET_CLS_ACT
} else if (!cl) {
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 4532659..ca0c296 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -88,9 +88,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_SUCCESS;
}
- kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_DROP;
+ return qdisc_drop(skb, sch);
}
static struct sk_buff *
^ permalink raw reply related
* Re: [Lksctp-developers] Bug: sctp packets are dropped after IPSEC rekeying (route cache issue)
From: David Miller @ 2012-05-04 14:48 UTC (permalink / raw)
To: nicolas.dichtel
Cc: vladislav.yasevich, babu.srinivasan, lksctp-developers,
linux-sctp, netdev, michael.kreuzer
In-Reply-To: <4FA3AA6A.4070503@6wind.com>
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Fri, 04 May 2012 12:07:38 +0200
> Finally, this patch was never integrated into the mainline. Should I
> rebase it on the head?
>
> I've attach the last approved patch.
>
> Here is the original thread:
> http://sourceforge.net/mailarchive/message.php?msg_id=25786006
Vlad no longer works for HP so your email likely will bounce, and
he will not see it.
His new email address is vyasevich@gmail.com, as per the MAINTAINERS
file.
^ permalink raw reply
* Re: [PATCHv3 6/6] mISDN: Help to identify the card
From: Paul Gortmaker @ 2012-05-04 14:48 UTC (permalink / raw)
To: Karsten Keil; +Cc: David Miller, netdev, Karsten Keil
In-Reply-To: <1336140935-25830-7-git-send-email-kkeil@linux-pingi.de>
On Fri, May 4, 2012 at 10:15 AM, Karsten Keil <kkeil@linux-pingi.de> wrote:
> From: Karsten Keil <isdn@linux-pingi.de>
>
> With multiple cards is hard to figure out which port caused trouble
> int the layer2 routines (e.g. got a timeout).
> Now we have the informations in the log output.
If you are in here changing all these printk(KERN_LEVEL ...) lines anyway,
then perhaps it is a good time to make use of pr_warn() and friends to
help avoid some multi-line fragmentation things like this:
> printk(KERN_WARNING
> "%s: windowar[%d] is NULL\n",
> - __func__, p1);
> + mISDNDevName4ch(&l2->ch), p1);
> l2->windowar[p1] = NULL;
Paul.
^ permalink raw reply
* Re: [PATCH net-next] net: skb_peek()/skb_peek_tail() cleanups
From: David Miller @ 2012-05-04 14:52 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1336136491.3752.318.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 04 May 2012 15:01:31 +0200
> On Tue, 2012-05-01 at 09:41 -0400, David Miller wrote:
>> From: Eric Dumazet <eric.dumazet@gmail.com>
>> Date: Tue, 01 May 2012 04:31:46 +0200
>>
>> > From: Eric Dumazet <edumazet@google.com>
>> >
>> > remove useless casts and rename variables for less confusion.
>> >
>> > Signed-off-by: Eric Dumazet <edumazet@google.com>
>>
>> Applied, I really need to get back to completing the list_head
>> conversion :-/
>
> Actually doubly linked lists everywhere has a performance issue.
>
> When we dequeue one skb, we must bring in cpu cache the next skb as
> well, to perform the unlink.
>
> In some places it would be better to not have a double linked list, and
> only perform a prefetch(skb->next).
Indeed, I'll keep this in mind.
^ permalink raw reply
* Re: [PATCH v3] bonding: don't increase rx_dropped after processing LACPDUs
From: David Miller @ 2012-05-04 14:53 UTC (permalink / raw)
To: jbohac; +Cc: eric.dumazet, fubar, andy, netdev
In-Reply-To: <20120504132824.GD32665@midget.suse.cz>
From: Jiri Bohac <jbohac@suse.cz>
Date: Fri, 4 May 2012 15:28:24 +0200
> On Fri, May 04, 2012 at 03:04:56PM +0200, Eric Dumazet wrote:
>> On Fri, 2012-05-04 at 14:19 +0200, Jiri Bohac wrote:
>> > if (likely(nskb)) {
>> > - recv_probe(nskb, bond, slave);
>> > + ret = recv_probe(nskb, bond, slave);
>> > dev_kfree_skb(nskb);
>> > + if (ret == RX_HANDLER_CONSUMED) {
>> > + kfree_skb(skb);
>>
>> consume_skb(skb) to not fool drop_monitor/dropwatch ?
>
> Thanks, fixed below:
You're doing the patch-as-reply thing again.
^ permalink raw reply
* Re: Fwd: Re: WARNING: at net/sched/sch_generic.c:256 dev_watchdog+0x277/0x280()
From: Alex Villacís Lasso @ 2012-05-04 14:57 UTC (permalink / raw)
To: netdev, Francois Romieu
In-Reply-To: <4FA2A6A4.1030308@ceibo.fiec.espol.edu.ec>
(Resending to netdev@vger.kernel.org since previous attempt was rejected as spam)
El 03/05/12 10:39, Alex Villacís Lasso escribió:
> Alex Villacís Lasso<avillaci@fiec.espol.edu.ec> :
> [...]
> > I am currently away from the target computer. How should I check for this? lspci?
>
> lspci can not tell much. Use 'dmesg | grep XID' instead.
[alex@karlalex linux-git]$ dmesg | grep -i xid
[ 10.647557] r8169 0000:02:00.0: eth0: RTL8168b/8111b at 0xffffc90000352000, 00:22:68:44:17:2f, XID 98500000 IRQ 43
> A complete dmesg would be welcome.
>
> It could help to know a few things :
> - does the problem qualify as a regression since some kernel version ?
> If so which one ?
I have only seen these messages since 3.4-rc1. Vanilla kernels up to 3.3, and stock Fedora 16 kernels (kernel-3.3.2-6.fc16.x86_64) did not display this problem. However, I cannot confirm that the latest stock kernel is free from the message, since I prefer
to run the latest RC kernel on my home machine.
> - can it be reproduced with a kernel that has not been vbox tainted ?
I will check this. However, since the message only appears after an hour of so of moderate bittorrent traffic, it might take a while to confirm.
> - does networking recover ?
It does recover, after a few seconds.
>
> Thanks.
>
> --
> Ueimor
>
^ permalink raw reply
* Re: [net v2 0/4][pull request] Intel Wired LAN Driver Updates
From: David Miller @ 2012-05-04 14:58 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, sassmann
In-Reply-To: <1336129504-29919-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Fri, 4 May 2012 04:05:00 -0700
> This series of patches contains fixes for ixgbe, igb and e1000.
>
> v2: Added e1000 patch to fix sparse warnings and igb/ixgbe to
> correct an issue of calling function to reset Tx queue in
> init path.
>
> The following are changes since commit 5a8887d39e1ba5ee2d4ccb94b14d6f2dce5ddfca:
> sungem: Fix WakeOnLan
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master`
I pulled, but what is that "`" character doing at the end of that GIT url?
I removed it when I pulled as you don't seem to have a "master`" branch in
your tree as far as I can tell.
^ permalink raw reply
* [PATCH net-next] tcp: be more strict before accepting ECN negociation
From: Eric Dumazet @ 2012-05-04 15:14 UTC (permalink / raw)
To: David Miller
Cc: netdev, Perry Lorier, Matt Mathis, Yuchung Cheng, Neal Cardwell,
Tom Herbert, Wilmer van der Gaast, Dave Täht, Ankur Jain
From: Eric Dumazet <edumazet@google.com>
It appears some networks play bad games with the two bits reserved for
ECN. This can trigger false congestion notifications and very slow
transferts.
Since RFC 3168 (6.1.1) forbids SYN packets to carry CT bits, we can
disable TCP ECN negociation if it happens we receive mangled CT bits in
the SYN packet.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Perry Lorier <perryl@google.com>
Cc: Matt Mathis <mattmathis@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Wilmer van der Gaast <wilmer@google.com>
Cc: Ankur Jain <jankur@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Dave Täht <dave.taht@bufferbloat.net>
---
include/net/tcp.h | 23 ++++++++++++++++-------
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index c826ed7..92faa6a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -367,13 +367,6 @@ static inline void tcp_dec_quickack_mode(struct sock *sk,
#define TCP_ECN_DEMAND_CWR 4
#define TCP_ECN_SEEN 8
-static __inline__ void
-TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
-{
- if (sysctl_tcp_ecn && th->ece && th->cwr)
- inet_rsk(req)->ecn_ok = 1;
-}
-
enum tcp_tw_status {
TCP_TW_SUCCESS = 0,
TCP_TW_RST = 1,
@@ -671,6 +664,22 @@ struct tcp_skb_cb {
#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
+/* RFC3168 : 6.1.1 SYN packets must not have ECT/ECN bits set
+ *
+ * If we receive a SYN packet with these bits set, it means a network is
+ * playing bad games with TOS bits. In order to avoid possible false congestion
+ * notifications, we disable TCP ECN negociation.
+ */
+static inline void
+TCP_ECN_create_request(struct request_sock *req, const struct sk_buff *skb)
+{
+ const struct tcphdr *th = tcp_hdr(skb);
+
+ if (sysctl_tcp_ecn && th->ece && th->cwr &&
+ INET_ECN_is_not_ect(TCP_SKB_CB(skb)->ip_dsfield))
+ inet_rsk(req)->ecn_ok = 1;
+}
+
/* Due to TSO, an SKB can be composed of multiple actual
* packets. To keep these tracked properly, we use this.
*/
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index cf97e98..4ff5e1f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1368,7 +1368,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop_and_free;
if (!want_cookie || tmp_opt.tstamp_ok)
- TCP_ECN_create_request(req, tcp_hdr(skb));
+ TCP_ECN_create_request(req, skb);
if (want_cookie) {
isn = cookie_v4_init_sequence(sk, skb, &req->mss);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 57b2109..078d039 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1140,7 +1140,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
treq->rmt_addr = ipv6_hdr(skb)->saddr;
treq->loc_addr = ipv6_hdr(skb)->daddr;
if (!want_cookie || tmp_opt.tstamp_ok)
- TCP_ECN_create_request(req, tcp_hdr(skb));
+ TCP_ECN_create_request(req, skb);
treq->iif = sk->sk_bound_dev_if;
^ permalink raw reply related
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