Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 0/2] fix kernel crash with macvtap on top of LRO
From: Michael S. Tsirkin @ 2013-02-07 21:33 UTC (permalink / raw)
  To: David Miller
  Cc: e1000-devel, linux-driver, netdev, jitendra.kalsaria,
	bruce.w.allan, jesse.brandeburg, eilong, john.r.fastabend,
	john.ronciak, sony.chacko, bhutchings, linux-kernel,
	jacob.e.keller
In-Reply-To: <20130207.131420.1211188723341167971.davem@davemloft.net>

On Thu, Feb 07, 2013 at 01:14:20PM -0500, David Miller wrote:
> From: Ben Hutchings <bhutchings@solarflare.com>
> Date: Thu, 7 Feb 2013 16:20:46 +0000
> 
> > If the consensus is still that we must preserve packets exactly (aside
> > from the usual modifications by IP routers) then LRO should be disabled
> > on all devices for which forwarding is enabled.
> 
> I believe this is still undoubtedly the consensus.

But we don't need to preserve the packets when passing them to macvtap
(which discards all this info smashing the packet into a single buffer anyway),
correct?
If true LRO with macvtap might be useful and so the patchset is probably
still the right thing to do to fix the macvtap crash. Makes sense?

We might want to add code to forward LRO status from macvlan
(not macvtap) back to the lowerdev, so that setting up forwarding
from macvlan disables LRO on the lowerdev, but that seems like another
issue.

-- 
MST

------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* [PATCH] drivers: net: Remove remaining alloc/OOM messages
From: Joe Perches @ 2013-02-07 21:46 UTC (permalink / raw)
  To: netdev
  Cc: linux-can, linux-kernel, e1000-devel, linux-usb, linux-wireless,
	ath9k-devel, wil6210, brcm80211-dev-list, devicetree-discuss

alloc failures already get standardized OOM
messages and a dump_stack.

For the affected mallocs around these OOM messages:

Converted kmallocs with multiplies to kmalloc_array.
Converted a kmalloc/memcpy to kmemdup.
Removed now unused stack variables.
Removed unnecessary parentheses.
Neatened alignment.

Signed-off-by: Joe Perches <joe@perches.com>
---
Let me know if you want multiple small patches instead.

 drivers/net/can/usb/ems_usb.c                      |  4 +-
 drivers/net/ethernet/amd/pcnet32.c                 | 47 +++++++---------------
 drivers/net/ethernet/freescale/gianfar.c           | 25 +++++-------
 drivers/net/ethernet/intel/e1000/e1000_main.c      | 14 ++-----
 drivers/net/ethernet/intel/ixgb/ixgb_main.c        | 10 +----
 drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c      |  4 +-
 drivers/net/ethernet/mellanox/mlx4/en_ethtool.c    |  2 -
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c     | 11 ++---
 drivers/net/ethernet/mellanox/mlx4/en_rx.c         |  6 +--
 drivers/net/ethernet/qlogic/qlge/qlge_main.c       | 22 ++++------
 drivers/net/ethernet/smsc/smsc9420.c               |  9 ++---
 drivers/net/usb/pegasus.c                          |  6 +--
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      | 11 ++---
 drivers/net/wireless/ath/ath9k/hw.c                |  7 +---
 drivers/net/wireless/ath/ath9k/rc.c                | 12 +-----
 drivers/net/wireless/ath/wil6210/txrx.c            |  2 -
 drivers/net/wireless/ath/wil6210/wmi.c             | 10 ++---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  5 +--
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      |  7 ++--
 drivers/net/wireless/mwl8k.c                       |  2 -
 20 files changed, 66 insertions(+), 150 deletions(-)

diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 0e7bde7..5f9a7ad 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -1019,10 +1019,8 @@ static int ems_usb_probe(struct usb_interface *intf,
 
 	dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
 				     sizeof(struct ems_cpc_msg), GFP_KERNEL);
-	if (!dev->tx_msg_buffer) {
-		dev_err(&intf->dev, "Couldn't alloc Tx buffer\n");
+	if (!dev->tx_msg_buffer)
 		goto cleanup_intr_in_buffer;
-	}
 
 	usb_set_intfdata(intf, dev);
 
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 74cfc01..797f847 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -494,19 +494,15 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev,
 	}
 	memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
 
-	new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
-				GFP_ATOMIC);
-	if (!new_dma_addr_list) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t),
+				    GFP_ATOMIC);
+	if (!new_dma_addr_list)
 		goto free_new_tx_ring;
-	}
 
-	new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
-				GFP_ATOMIC);
-	if (!new_skb_list) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *),
+			       GFP_ATOMIC);
+	if (!new_skb_list)
 		goto free_new_lists;
-	}
 
 	kfree(lp->tx_skbuff);
 	kfree(lp->tx_dma_addr);
@@ -564,19 +560,14 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
 	}
 	memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
 
-	new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
-				GFP_ATOMIC);
-	if (!new_dma_addr_list) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t), GFP_ATOMIC);
+	if (!new_dma_addr_list)
 		goto free_new_rx_ring;
-	}
 
-	new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
-				GFP_ATOMIC);
-	if (!new_skb_list) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *),
+			       GFP_ATOMIC);
+	if (!new_skb_list)
 		goto free_new_lists;
-	}
 
 	/* first copy the current receive buffers */
 	overlap = min(size, lp->rx_ring_size);
@@ -1933,31 +1924,23 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
 
 	lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t),
 				  GFP_ATOMIC);
-	if (!lp->tx_dma_addr) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	if (!lp->tx_dma_addr)
 		return -ENOMEM;
-	}
 
 	lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t),
 				  GFP_ATOMIC);
-	if (!lp->rx_dma_addr) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	if (!lp->rx_dma_addr)
 		return -ENOMEM;
-	}
 
 	lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *),
 				GFP_ATOMIC);
-	if (!lp->tx_skbuff) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	if (!lp->tx_skbuff)
 		return -ENOMEM;
-	}
 
 	lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *),
 				GFP_ATOMIC);
-	if (!lp->rx_skbuff) {
-		netif_err(lp, drv, dev, "Memory allocation failed\n");
+	if (!lp->rx_skbuff)
 		return -ENOMEM;
-	}
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 75734bf..ab32bd0 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -277,14 +277,12 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 	/* Setup the skbuff rings */
 	for (i = 0; i < priv->num_tx_queues; i++) {
 		tx_queue = priv->tx_queue[i];
-		tx_queue->tx_skbuff = kmalloc(sizeof(*tx_queue->tx_skbuff) *
-					      tx_queue->tx_ring_size,
-					      GFP_KERNEL);
-		if (!tx_queue->tx_skbuff) {
-			netif_err(priv, ifup, ndev,
-				  "Could not allocate tx_skbuff\n");
+		tx_queue->tx_skbuff =
+			kmalloc_array(tx_queue->tx_ring_size,
+				      sizeof(*tx_queue->tx_skbuff),
+				      GFP_KERNEL);
+		if (!tx_queue->tx_skbuff)
 			goto cleanup;
-		}
 
 		for (k = 0; k < tx_queue->tx_ring_size; k++)
 			tx_queue->tx_skbuff[k] = NULL;
@@ -292,15 +290,12 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 
 	for (i = 0; i < priv->num_rx_queues; i++) {
 		rx_queue = priv->rx_queue[i];
-		rx_queue->rx_skbuff = kmalloc(sizeof(*rx_queue->rx_skbuff) *
-					      rx_queue->rx_ring_size,
-					      GFP_KERNEL);
-
-		if (!rx_queue->rx_skbuff) {
-			netif_err(priv, ifup, ndev,
-				  "Could not allocate rx_skbuff\n");
+		rx_queue->rx_skbuff =
+			kmalloc_array(rx_queue->rx_ring_size,
+				      sizeof(*rx_queue->rx_skbuff),
+				      GFP_KERNEL);
+		if (!rx_queue->rx_skbuff)
 			goto cleanup;
-		}
 
 		for (j = 0; j < rx_queue->rx_ring_size; j++)
 			rx_queue->rx_skbuff[j] = NULL;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index b20fff1..d947e3a 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1509,11 +1509,8 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
 
 	size = sizeof(struct e1000_buffer) * txdr->count;
 	txdr->buffer_info = vzalloc(size);
-	if (!txdr->buffer_info) {
-		e_err(probe, "Unable to allocate memory for the Tx descriptor "
-		      "ring\n");
+	if (!txdr->buffer_info)
 		return -ENOMEM;
-	}
 
 	/* round up to nearest 4K */
 
@@ -1704,11 +1701,8 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
 
 	size = sizeof(struct e1000_buffer) * rxdr->count;
 	rxdr->buffer_info = vzalloc(size);
-	if (!rxdr->buffer_info) {
-		e_err(probe, "Unable to allocate memory for the Rx descriptor "
-		      "ring\n");
+	if (!rxdr->buffer_info)
 		return -ENOMEM;
-	}
 
 	desc_len = sizeof(struct e1000_rx_desc);
 
@@ -2252,10 +2246,8 @@ static void e1000_set_rx_mode(struct net_device *netdev)
 	int mta_reg_count = E1000_NUM_MTA_REGISTERS;
 	u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
 
-	if (!mcarray) {
-		e_err(probe, "memory allocation failed\n");
+	if (!mcarray)
 		return;
-	}
 
 	/* Check for Promiscuous and All Multicast modes */
 
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index c756412..ea48083 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -708,11 +708,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
 
 	size = sizeof(struct ixgb_buffer) * txdr->count;
 	txdr->buffer_info = vzalloc(size);
-	if (!txdr->buffer_info) {
-		netif_err(adapter, probe, adapter->netdev,
-			  "Unable to allocate transmit descriptor ring memory\n");
+	if (!txdr->buffer_info)
 		return -ENOMEM;
-	}
 
 	/* round up to nearest 4K */
 
@@ -797,11 +794,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
 
 	size = sizeof(struct ixgb_buffer) * rxdr->count;
 	rxdr->buffer_info = vzalloc(size);
-	if (!rxdr->buffer_info) {
-		netif_err(adapter, probe, adapter->netdev,
-			  "Unable to allocate receive descriptor ring\n");
+	if (!rxdr->buffer_info)
 		return -ENOMEM;
-	}
 
 	/* Round up to nearest 4K */
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index c116884..f58db45 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -716,10 +716,8 @@ int ixgbe_setup_fcoe_ddp_resources(struct ixgbe_adapter *adapter)
 
 	/* Extra buffer to be shared by all DDPs for HW work around */
 	buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
-	if (!buffer) {
-		e_err(drv, "failed to allocate extra DDP buffer\n");
+	if (!buffer)
 		return -ENOMEM;
-	}
 
 	dma = dma_map_single(dev, buffer, IXGBE_FCBUFF_MIN, DMA_FROM_DEVICE);
 	if (dma_mapping_error(dev, dma)) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index f523f02..1dc924a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -744,7 +744,6 @@ static int add_ip_rule(struct mlx4_en_priv *priv,
 	spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
 	spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
 	if (!spec_l2 || !spec_l3) {
-		en_err(priv, "Fail to alloc ethtool rule.\n");
 		err = -ENOMEM;
 		goto free_spec;
 	}
@@ -785,7 +784,6 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv,
 	spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
 	spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL);
 	if (!spec_l2 || !spec_l3 || !spec_l4) {
-		en_err(priv, "Fail to alloc ethtool rule.\n");
 		err = -ENOMEM;
 		goto free_spec;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index ac1c14f..1db3b22 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -482,7 +482,6 @@ static void mlx4_en_cache_mclist(struct net_device *dev)
 	netdev_for_each_mc_addr(ha, dev) {
 		tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
 		if (!tmp) {
-			en_err(priv, "failed to allocate multicast list\n");
 			mlx4_en_clear_list(dev);
 			return;
 		}
@@ -526,14 +525,12 @@ static void update_mclist_flags(struct mlx4_en_priv *priv,
 			}
 		}
 		if (!found) {
-			new_mc = kmalloc(sizeof(struct mlx4_en_mc_list),
+			new_mc = kmemdup(src_tmp,
+					 sizeof(struct mlx4_en_mc_list),
 					 GFP_KERNEL);
-			if (!new_mc) {
-				en_err(priv, "Failed to allocate current multicast list\n");
+			if (!new_mc)
 				return;
-			}
-			memcpy(new_mc, src_tmp,
-			       sizeof(struct mlx4_en_mc_list));
+
 			new_mc->action = MCLIST_ADD;
 			list_add_tail(&new_mc->list, dst);
 		}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index fed26d8..06c3121 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -835,11 +835,9 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
 	struct mlx4_qp_context *context;
 	int err = 0;
 
-	context = kmalloc(sizeof *context , GFP_KERNEL);
-	if (!context) {
-		en_err(priv, "Failed to allocate qp context\n");
+	context = kmalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
 		return -ENOMEM;
-	}
 
 	err = mlx4_qp_alloc(mdev->dev, qpn, qp);
 	if (err) {
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 325627e..b13ab54 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -2920,14 +2920,11 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev,
 		/*
 		 * Allocate small buffer queue control blocks.
 		 */
-		rx_ring->sbq =
-		    kmalloc(rx_ring->sbq_len * sizeof(struct bq_desc),
-			    GFP_KERNEL);
-		if (rx_ring->sbq == NULL) {
-			netif_err(qdev, ifup, qdev->ndev,
-				  "Small buffer queue control block allocation failed.\n");
+		rx_ring->sbq = kmalloc_array(rx_ring->sbq_len,
+					     sizeof(struct bq_desc),
+					     GFP_KERNEL);
+		if (rx_ring->sbq == NULL)
 			goto err_mem;
-		}
 
 		ql_init_sbq_ring(qdev, rx_ring);
 	}
@@ -2948,14 +2945,11 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev,
 		/*
 		 * Allocate large buffer queue control blocks.
 		 */
-		rx_ring->lbq =
-		    kmalloc(rx_ring->lbq_len * sizeof(struct bq_desc),
-			    GFP_KERNEL);
-		if (rx_ring->lbq == NULL) {
-			netif_err(qdev, ifup, qdev->ndev,
-				  "Large buffer queue control block allocation failed.\n");
+		rx_ring->lbq = kmalloc_array(rx_ring->lbq_len,
+					     sizeof(struct bq_desc),
+					     GFP_KERNEL);
+		if (rx_ring->lbq == NULL)
 			goto err_mem;
-		}
 
 		ql_init_lbq_ring(qdev, rx_ring);
 	}
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index ecfb436..d457fa2 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -1250,12 +1250,11 @@ static int smsc9420_alloc_tx_ring(struct smsc9420_pdata *pd)
 
 	BUG_ON(!pd->tx_ring);
 
-	pd->tx_buffers = kmalloc((sizeof(struct smsc9420_ring_info) *
-		TX_RING_SIZE), GFP_KERNEL);
-	if (!pd->tx_buffers) {
-		smsc_warn(IFUP, "Failed to allocated tx_buffers");
+	pd->tx_buffers = kmalloc_array(TX_RING_SIZE,
+				       sizeof(struct smsc9420_ring_info),
+				       GFP_KERNEL);
+	if (!pd->tx_buffers)
 		return -ENOMEM;
-	}
 
 	/* Initialize the TX Ring */
 	for (i = 0; i < TX_RING_SIZE; i++) {
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 8ee5ab0..73051d1 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -149,11 +149,9 @@ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
 	DECLARE_WAITQUEUE(wait, current);
 
 	buffer = kmalloc(size, GFP_KERNEL);
-	if (!buffer) {
-		netif_warn(pegasus, drv, pegasus->net,
-			   "out of memory in %s\n", __func__);
+	if (!buffer)
 		return -ENOMEM;
-	}
+
 	add_wait_queue(&pegasus->ctrl_wait, &wait);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	while (pegasus->flags & ETH_REGS_CHANGED)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index b6a5a08..3ad1fd0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1196,20 +1196,17 @@ void ath9k_rx_cleanup(struct ath9k_htc_priv *priv)
 
 int ath9k_rx_init(struct ath9k_htc_priv *priv)
 {
-	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	struct ath9k_htc_rxbuf *rxbuf;
 	int i = 0;
 
 	INIT_LIST_HEAD(&priv->rx.rxbuf);
 	spin_lock_init(&priv->rx.rxbuflock);
 
 	for (i = 0; i < ATH9K_HTC_RXBUF; i++) {
-		rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL);
-		if (rxbuf == NULL) {
-			ath_err(common, "Unable to allocate RX buffers\n");
+		struct ath9k_htc_rxbuf *rxbuf =
+			kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL);
+		if (rxbuf == NULL)
 			goto err;
-		}
+
 		list_add_tail(&rxbuf->list, &priv->rx.rxbuf);
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 42cf3c7..2a2ae40 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2981,13 +2981,8 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 	struct ath_gen_timer *timer;
 
 	timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
-
-	if (timer == NULL) {
-		ath_err(ath9k_hw_common(ah),
-			"Failed to allocate memory for hw timer[%d]\n",
-			timer_index);
+	if (timer == NULL)
 		return NULL;
-	}
 
 	/* allocate a hardware generic timer slot */
 	timer_table->timers[timer_index] = timer;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 714558d..faa752b 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1452,17 +1452,7 @@ static void ath_rate_free(void *priv)
 
 static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 {
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *rate_priv;
-
-	rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
-	if (!rate_priv) {
-		ath_err(ath9k_hw_common(sc->sc_ah),
-			"Unable to allocate private rc structure\n");
-		return NULL;
-	}
-
-	return rate_priv;
+	return kzalloc(sizeof(struct ath_rate_priv), gfp);
 }
 
 static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index f29c294..23b1afc 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -74,8 +74,6 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
 	vring->swtail = 0;
 	vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL);
 	if (!vring->ctx) {
-		wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n",
-			vring->size);
 		vring->va = NULL;
 		return -ENOMEM;
 	}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 12915f6..5fb960e 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -587,11 +587,9 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 		evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
 					     event.wmi) + len, 4),
 			      GFP_KERNEL);
-		if (!evt) {
-			wil_err(wil, "kmalloc for WMI event (%d) failed\n",
-				len);
+		if (!evt)
 			return;
-		}
+
 		evt->event.hdr = hdr;
 		cmd = (void *)&evt->event.wmi;
 		wil_memcpy_fromio_32(cmd, src, len);
@@ -838,10 +836,8 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
 	int rc;
 	u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
 	struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
-	if (!cmd) {
-		wil_err(wil, "kmalloc(%d) failed\n", len);
+	if (!cmd)
 		return -ENOMEM;
-	}
 
 	cmd->mgmt_frm_type = type;
 	/* BUG: FW API define ieLen as u8. Will fix FW */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 7fef9b5..6d786a2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1445,10 +1445,9 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 
 	if (bus->rxblen)
 		buf = vzalloc(bus->rxblen);
-	if (!buf) {
-		brcmf_err("no memory for control frame\n");
+	if (!buf)
 		goto done;
-	}
+
 	rbuf = bus->rxbuf;
 	pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
 	if (pad)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index e15630c..bc5a042 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -354,11 +354,10 @@ brcmf_usbdev_qinit(struct list_head *q, int qsize)
 	int i;
 	struct brcmf_usbreq *req, *reqs;
 
-	reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC);
-	if (reqs == NULL) {
-		brcmf_err("fail to allocate memory!\n");
+	reqs = kcalloc(qsize, sizeof(struct brcmf_usbreq), GFP_ATOMIC);
+	if (reqs == NULL)
 		return NULL;
-	}
+
 	req = reqs;
 
 	for (i = 0; i < qsize; i++) {
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 224cf91..e31f779 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1146,7 +1146,6 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
 
 	rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
 	if (rxq->buf == NULL) {
-		wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
 		return -ENOMEM;
 	}
@@ -1439,7 +1438,6 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 
 	txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
-		wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
 		return -ENOMEM;
 	}



^ permalink raw reply related

* Re: [PATCH] drivers: net: Remove remaining alloc/OOM messages
From: Arend van Spriel @ 2013-02-07 22:07 UTC (permalink / raw)
  To: Joe Perches
  Cc: netdev, linux-can, linux-kernel, e1000-devel, linux-usb,
	linux-wireless, ath9k-devel, wil6210, brcm80211-dev-list,
	devicetree-discuss
In-Reply-To: <1360273587.27863.15.camel@joe-AO722>

On 02/07/2013 10:46 PM, Joe Perches wrote:
> alloc failures already get standardized OOM
> messages and a dump_stack.
> 
> For the affected mallocs around these OOM messages:
> 
> Converted kmallocs with multiplies to kmalloc_array.
> Converted a kmalloc/memcpy to kmemdup.
> Removed now unused stack variables.
> Removed unnecessary parentheses.
> Neatened alignment.

for brcm80211 driver files listed below:

Acked-by: Arend van Spriel <arend@broadcom.com>
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> Let me know if you want multiple small patches instead.
> 
>  drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  5 +--
>  drivers/net/wireless/brcm80211/brcmfmac/usb.c      |  7 ++--



^ permalink raw reply

* Re: [PATCH 0/2] fix kernel crash with macvtap on top of LRO
From: Ben Hutchings @ 2013-02-07 22:31 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: e1000-devel, netdev, jitendra.kalsaria, bruce.w.allan,
	jesse.brandeburg, eilong, john.r.fastabend, john.ronciak,
	sony.chacko, linux-driver, David Miller, linux-kernel,
	jacob.e.keller
In-Reply-To: <20130207213315.GB5064@redhat.com>

On Thu, 2013-02-07 at 23:33 +0200, Michael S. Tsirkin wrote:
> On Thu, Feb 07, 2013 at 01:14:20PM -0500, David Miller wrote:
> > From: Ben Hutchings <bhutchings@solarflare.com>
> > Date: Thu, 7 Feb 2013 16:20:46 +0000
> > 
> > > If the consensus is still that we must preserve packets exactly (aside
> > > from the usual modifications by IP routers) then LRO should be disabled
> > > on all devices for which forwarding is enabled.
> > 
> > I believe this is still undoubtedly the consensus.
> 
> But we don't need to preserve the packets when passing them to macvtap
> (which discards all this info smashing the packet into a single buffer anyway),
> correct?

macvtap_skb_to_vnet_hdr() certainly seems to be trying to preserve all
the packet information.

> If true LRO with macvtap might be useful and so the patchset is probably
> still the right thing to do to fix the macvtap crash. Makes sense?

If macvtap+virtio_net is expected to re-segment then this is fine.  But
I don't see why it should be different from other uses of macvlan.

> We might want to add code to forward LRO status from macvlan
> (not macvtap) back to the lowerdev, so that setting up forwarding
> from macvlan disables LRO on the lowerdev, but that seems like another
> issue.

I think it's the same issue!

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: [PATCH v9 net-next 00/12] Add basic VLAN support to bridges
From: Vlad Yasevich @ 2013-02-07 22:48 UTC (permalink / raw)
  Cc: Stephen Hemminger, bridge, davem, netdev
In-Reply-To: <510FE8BE.4040302@redhat.com>

On 02/04/2013 11:58 AM, Vlad Yasevich wrote:
> On 02/04/2013 11:24 AM, Stephen Hemminger wrote:
>> One thing I am not clear about is whether is supposed to be just
>> a simple filter of VLAN traffic, or a full VLAN aware bridge.
>
> I started with the concept of basic VLAN filtering, but it has been
> morphing into more of a VLAN away bridge.
>
>>
>> The change to make FDB entries per-VLAN seems to be the biggest tipping
>> point into a full VLAN bridge. I am concerned that might break existing
>> API's and Spanning Tree (internal and external).
>>
>
> I debated for a while about whether per-VLAN FDB entries were needed.
> The typing point was that without it, you may end up with flopping FDB
> and possible packet drops or vlan leaks, if say 2 different VMs used the
> same MAC but different VLANs.  Without it, there is an exploitable gap.
>
> I've also tried to separate FDB code changes as much as possible.  If
> you really thing this is a big risk and a barrier to entry, then we can
> drop them.  I am just concerned about the hole I described above, but I
> guess it is not much different then what's there now.
>

So I played with STP for quite a bit and found the FDB changes have 
absolutely no effect on operation of STP.
Since all the vlan filtering code is mostly in forwarding path, STP 
works just fine.
Looking at STP code (the one in the kernel), I don't see any 
dependencies on FDB.  The only userspace code I can find is from here
git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/rstp.git.  That 
only seems to ask for RTM_GETLINK, and there you will not get any vlan 
information if you don't set the filter flags.

So, I don't see any API impact as far as STP is concerned.

-vlad

^ permalink raw reply

* Re: [PATCH v9 net-next 00/12] Add basic VLAN support to bridges
From: Stephen Hemminger @ 2013-02-07 22:57 UTC (permalink / raw)
  To: vyasevic; +Cc: bridge, davem, netdev
In-Reply-To: <51142F20.4050008@redhat.com>

On Thu, 07 Feb 2013 17:48:00 -0500
Vlad Yasevich <vyasevic@redhat.com> wrote:

> On 02/04/2013 11:58 AM, Vlad Yasevich wrote:
> > On 02/04/2013 11:24 AM, Stephen Hemminger wrote:
> >> One thing I am not clear about is whether is supposed to be just
> >> a simple filter of VLAN traffic, or a full VLAN aware bridge.
> >
> > I started with the concept of basic VLAN filtering, but it has been
> > morphing into more of a VLAN away bridge.
> >
> >>
> >> The change to make FDB entries per-VLAN seems to be the biggest tipping
> >> point into a full VLAN bridge. I am concerned that might break existing
> >> API's and Spanning Tree (internal and external).
> >>
> >
> > I debated for a while about whether per-VLAN FDB entries were needed.
> > The typing point was that without it, you may end up with flopping FDB
> > and possible packet drops or vlan leaks, if say 2 different VMs used the
> > same MAC but different VLANs.  Without it, there is an exploitable gap.
> >
> > I've also tried to separate FDB code changes as much as possible.  If
> > you really thing this is a big risk and a barrier to entry, then we can
> > drop them.  I am just concerned about the hole I described above, but I
> > guess it is not much different then what's there now.
> >
> 
> So I played with STP for quite a bit and found the FDB changes have 
> absolutely no effect on operation of STP.
> Since all the vlan filtering code is mostly in forwarding path, STP 
> works just fine.
> Looking at STP code (the one in the kernel), I don't see any 
> dependencies on FDB.  The only userspace code I can find is from here
> git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/rstp.git.  That 
> only seems to ask for RTM_GETLINK, and there you will not get any vlan 
> information if you don't set the filter flags.
> 
> So, I don't see any API impact as far as STP is concerned.

Good, does bridge command (in newer iproute2) still work?

^ permalink raw reply

* Re: [PATCH v9 net-next 00/12] Add basic VLAN support to bridges
From: Vlad Yasevich @ 2013-02-07 23:00 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: bridge, davem, netdev
In-Reply-To: <20130207145755.5a65062a@nehalam.linuxnetplumber.net>

On 02/07/2013 05:57 PM, Stephen Hemminger wrote:
> On Thu, 07 Feb 2013 17:48:00 -0500
> Vlad Yasevich <vyasevic@redhat.com> wrote:
>
>> On 02/04/2013 11:58 AM, Vlad Yasevich wrote:
>>> On 02/04/2013 11:24 AM, Stephen Hemminger wrote:
>>>> One thing I am not clear about is whether is supposed to be just
>>>> a simple filter of VLAN traffic, or a full VLAN aware bridge.
>>>
>>> I started with the concept of basic VLAN filtering, but it has been
>>> morphing into more of a VLAN away bridge.
>>>
>>>>
>>>> The change to make FDB entries per-VLAN seems to be the biggest tipping
>>>> point into a full VLAN bridge. I am concerned that might break existing
>>>> API's and Spanning Tree (internal and external).
>>>>
>>>
>>> I debated for a while about whether per-VLAN FDB entries were needed.
>>> The typing point was that without it, you may end up with flopping FDB
>>> and possible packet drops or vlan leaks, if say 2 different VMs used the
>>> same MAC but different VLANs.  Without it, there is an exploitable gap.
>>>
>>> I've also tried to separate FDB code changes as much as possible.  If
>>> you really thing this is a big risk and a barrier to entry, then we can
>>> drop them.  I am just concerned about the hole I described above, but I
>>> guess it is not much different then what's there now.
>>>
>>
>> So I played with STP for quite a bit and found the FDB changes have
>> absolutely no effect on operation of STP.
>> Since all the vlan filtering code is mostly in forwarding path, STP
>> works just fine.
>> Looking at STP code (the one in the kernel), I don't see any
>> dependencies on FDB.  The only userspace code I can find is from here
>> git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/rstp.git.  That
>> only seems to ask for RTM_GETLINK, and there you will not get any vlan
>> information if you don't set the filter flags.
>>
>> So, I don't see any API impact as far as STP is concerned.
>
> Good, does bridge command (in newer iproute2) still work?
>

Yes.  I have patches to it enable the vlan functionality, but I haven't 
posted them since I wanted the kernel pieces including the API to get 
accepted.

-vlad

^ permalink raw reply

* Re: [PATCH] drivers: net: Remove remaining alloc/OOM messages
From: Marc Kleine-Budde @ 2013-02-07 23:29 UTC (permalink / raw)
  To: Joe Perches
  Cc: netdev, linux-can, linux-kernel, e1000-devel, linux-usb,
	linux-wireless, ath9k-devel, wil6210, brcm80211-dev-list,
	devicetree-discuss
In-Reply-To: <1360273587.27863.15.camel@joe-AO722>

[-- Attachment #1: Type: text/plain, Size: 927 bytes --]

On 02/07/2013 10:46 PM, Joe Perches wrote:
> alloc failures already get standardized OOM
> messages and a dump_stack.
> 
> For the affected mallocs around these OOM messages:
> 
> Converted kmallocs with multiplies to kmalloc_array.
> Converted a kmalloc/memcpy to kmemdup.
> Removed now unused stack variables.
> Removed unnecessary parentheses.
> Neatened alignment.
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> Let me know if you want multiple small patches instead.
> 
>  drivers/net/can/usb/ems_usb.c                      |  4 +-

For ems_usb.c

Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>

regards,
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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

^ permalink raw reply

* [PATCH 1/1] eventfd: implementation of EFD_MASK flag
From: Martin Sustrik @ 2013-02-07 23:29 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Sha Zhengju, linux-fsdevel,
	linux-kernel
  Cc: netdev, Martin Sustrik

When implementing network protocols in user space, one has to implement
fake user-space file descriptors to represent the sockets for the protocol.

While all the BSD socket API functionality for such descriptors may be faked as
well (myproto_send(), myproto_recv() etc.) this approach doesn't work for
polling  (select, poll, epoll). And unfortunately, sockets that can't be polled
on allow only for building the simplest possible applications. Basically, you
can build a simple client, but once you want to implement a server handling
many sockets in parallel, you are stuck.

However, to do polling, real system-level file descriptor is needed,
not a fake one.

In theory, eventfd may be used for this purpose, except that it is well suited
only for signaling POLLIN. With some hacking it can be also used to signal
POLLOUT and POLLERR, but:

I.  There's no way to signal POLLPRI, POLLHUP etc.
II. There's no way to signal arbitraty combination of POLL* flags. Most notably,
    !POLLIN & !POLLOUT, which is a perfectly valid combination for a network
    protocol (rx buffer is empty and tx buffer is full), cannot be signaled
    using current implementation of eventfd.

This patch implements new EFD_MASK flag which attempts to solve this problem.

Additionally, when implementing network protocols in user space, there's a
need to associate user-space state with the each "socket". If eventfd object is
used as a reference to the socket, it should be possible to associate an opaque
pointer to user-space data with it.

The semantics of EFD_MASK are as follows:

eventfd(2):

If eventfd is created with EFD_MASK flag set, it is initialised in such a way
as to signal no events on the file descriptor when it is polled on. 'initval'
argument is ignored.

write(2):

User is allowed to write only buffers containing the following structure:

struct efd_mask {
  short events;
  void *ptr;
};

The value of 'events' should be any combination of event flags as defined by
poll(2) function (POLLIN, POLLOUT, POLLERR, POLLHUP etc.) Specified events will
be signaled when polling (select, poll, epoll) on the eventfd is done later on.
'ptr' is an opaque pointer that is not interpreted by eventfd object.

read(2):

User is allowed to read an efd_mask structure from the eventfd marked by
EFD_MASK. Returned value shall be the last one written to the eventfd.

select(2), poll(2) and similar:

When polling on the eventfd marked by EFD_MASK flag, all the events specified
in last written 'events' field shall be signaled.

Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
---
 fs/eventfd.c            |  105 ++++++++++++++++++++++++++++++++++++-----------
 include/linux/eventfd.h |    3 +-
 2 files changed, 83 insertions(+), 25 deletions(-)

diff --git a/fs/eventfd.c b/fs/eventfd.c
index 35470d9..9fec49f 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -2,6 +2,7 @@
  *  fs/eventfd.c
  *
  *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *  Copyright (C) 2013  Martin Sustrik <sustrik@250bpm.com>
  *
  */
 
@@ -22,18 +23,26 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+struct eventfd_mask {
+	short events;
+	void *ptr;
+};
+
 struct eventfd_ctx {
 	struct kref kref;
 	wait_queue_head_t wqh;
-	/*
-	 * Every time that a write(2) is performed on an eventfd, the
-	 * value of the __u64 being written is added to "count" and a
-	 * wakeup is performed on "wqh". A read(2) will return the "count"
-	 * value to userspace, and will reset "count" to zero. The kernel
-	 * side eventfd_signal() also, adds to the "count" counter and
-	 * issue a wakeup.
-	 */
-	__u64 count;
+	union {
+		/*
+		 * Every time that a write(2) is performed on an eventfd, the
+		 * value of the __u64 being written is added to "count" and a
+		 * wakeup is performed on "wqh". A read(2) will return the
+		 * "count" value to userspace, and will reset "count" to zero.
+		 * The kernel side eventfd_signal() also, adds to the "count"
+		 * counter and issue a wakeup.
+		 */
+		__u64 count;
+		struct eventfd_mask mask;
+	};
 	unsigned int flags;
 };
 
@@ -55,6 +64,9 @@ __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
 {
 	unsigned long flags;
 
+	/* This function should never be used with eventfd in the mask mode. */
+	BUG_ON(ctx->flags & EFD_MASK);
+
 	spin_lock_irqsave(&ctx->wqh.lock, flags);
 	if (ULLONG_MAX - ctx->count < n)
 		n = ULLONG_MAX - ctx->count;
@@ -123,12 +135,16 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait)
 	poll_wait(file, &ctx->wqh, wait);
 
 	spin_lock_irqsave(&ctx->wqh.lock, flags);
-	if (ctx->count > 0)
-		events |= POLLIN;
-	if (ctx->count == ULLONG_MAX)
-		events |= POLLERR;
-	if (ULLONG_MAX - 1 > ctx->count)
-		events |= POLLOUT;
+	if (ctx->flags & EFD_MASK) {
+		events = ctx->mask.events;
+	} else {
+		if (ctx->count > 0)
+			events |= POLLIN;
+		if (ctx->count == ULLONG_MAX)
+			events |= POLLERR;
+		if (ULLONG_MAX - 1 > ctx->count)
+			events |= POLLOUT;
+	}
 	spin_unlock_irqrestore(&ctx->wqh.lock, flags);
 
 	return events;
@@ -158,6 +174,9 @@ int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_t *wait,
 {
 	unsigned long flags;
 
+	/* This function should never be used with eventfd in the mask mode. */
+	BUG_ON(ctx->flags & EFD_MASK);
+
 	spin_lock_irqsave(&ctx->wqh.lock, flags);
 	eventfd_ctx_do_read(ctx, cnt);
 	__remove_wait_queue(&ctx->wqh, wait);
@@ -188,6 +207,9 @@ ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait, __u64 *cnt)
 	ssize_t res;
 	DECLARE_WAITQUEUE(wait, current);
 
+	/* This function should never be used with eventfd in the mask mode. */
+	BUG_ON(ctx->flags & EFD_MASK);
+
 	spin_lock_irq(&ctx->wqh.lock);
 	*cnt = 0;
 	res = -EAGAIN;
@@ -230,13 +252,23 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
 	ssize_t res;
 	__u64 cnt;
 
-	if (count < sizeof(cnt))
-		return -EINVAL;
-	res = eventfd_ctx_read(ctx, file->f_flags & O_NONBLOCK, &cnt);
-	if (res < 0)
+	if (ctx->flags & EFD_MASK) {
+		spin_lock_irq(&ctx->wqh.lock);
+		if (count < sizeof(ctx->mask))
+			return -EINVAL;
+		res = copy_to_user(buf, &ctx->mask, sizeof(ctx->mask)) ?
+			-EFAULT : sizeof(ctx->mask);
+		spin_unlock_irq(&ctx->wqh.lock);
 		return res;
-
-	return put_user(cnt, (__u64 __user *) buf) ? -EFAULT : sizeof(cnt);
+	} else {
+		if (count < sizeof(cnt))
+			return -EINVAL;
+		res = eventfd_ctx_read(ctx, file->f_flags & O_NONBLOCK, &cnt);
+		if (res < 0)
+			return res;
+		return put_user(cnt, (__u64 __user *) buf) ?
+			-EFAULT : sizeof(cnt);
+	}
 }
 
 static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
@@ -247,6 +279,21 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
 	__u64 ucnt;
 	DECLARE_WAITQUEUE(wait, current);
 
+	if (ctx->flags & EFD_MASK) {
+		if (count < sizeof(ctx->mask))
+			return -EINVAL;
+		spin_lock_irq(&ctx->wqh.lock);
+		if (copy_from_user(&ctx->mask, buf, sizeof(ctx->mask))) {
+			spin_unlock_irq(&ctx->wqh.lock);
+			return -EFAULT;
+		}
+		if (waitqueue_active(&ctx->wqh))
+			wake_up_locked_poll(&ctx->wqh,
+				(unsigned long)ctx->mask.events);
+		spin_unlock_irq(&ctx->wqh.lock);
+		return sizeof(ctx->mask);
+	}
+
 	if (count < sizeof(ucnt))
 		return -EINVAL;
 	if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
@@ -293,8 +340,13 @@ static int eventfd_show_fdinfo(struct seq_file *m, struct file *f)
 	int ret;
 
 	spin_lock_irq(&ctx->wqh.lock);
-	ret = seq_printf(m, "eventfd-count: %16llx\n",
-			 (unsigned long long)ctx->count);
+	if (ctx->flags & EFD_MASK) {
+		ret = seq_printf(m, "eventfd-mask: %x\n",
+				 (unsigned)ctx->mask.events);
+	} else {
+		ret = seq_printf(m, "eventfd-count: %16llx\n",
+				 (unsigned long long)ctx->count);
+	}
 	spin_unlock_irq(&ctx->wqh.lock);
 
 	return ret;
@@ -412,7 +464,12 @@ struct file *eventfd_file_create(unsigned int count, int flags)
 
 	kref_init(&ctx->kref);
 	init_waitqueue_head(&ctx->wqh);
-	ctx->count = count;
+	if (flags & EFD_MASK) {
+		ctx->mask.events = 0;
+		ctx->mask.ptr = NULL;
+	} else {
+		ctx->count = count;
+	}
 	ctx->flags = flags;
 
 	file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 3c3ef19..b806d2b 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -20,11 +20,12 @@
  * shared O_* flags.
  */
 #define EFD_SEMAPHORE (1 << 0)
+#define EFD_MASK (1 << 1)
 #define EFD_CLOEXEC O_CLOEXEC
 #define EFD_NONBLOCK O_NONBLOCK
 
 #define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
-#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE)
+#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE | EFD_MASK)
 
 #ifdef CONFIG_EVENTFD
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH] tg3: Add BCM57766 to PCI device table
From: Joerie de Gram @ 2013-02-07 23:31 UTC (permalink / raw)
  To: mcarlson, mchan; +Cc: netdev

The BCM57766 (as found in recent Apple mac mini models) appears to be
supported by the driver, but lacks an entry in the PCI device table.

Signed-off-by: Joerie de Gram <j.de.gram@gmail.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index bdb0869..214b27e 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -323,6 +323,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57766)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
 	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH] l2tp: dont play with skb->truesize
From: Eric Dumazet @ 2013-02-08  0:00 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, James Chapman, Andrew Savchenko

From: Eric Dumazet <edumazet@google.com>

Andrew Savchenko reported a DNS failure and we diagnosed that
some UDP sockets were unable to send more packets because their
sk_wmem_alloc was corrupted after a while (tx_queue column in
following trace)

$ cat /proc/net/udp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops             
...
  459: 00000000:0270 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 4507 2 ffff88003d612380 0          
  466: 00000000:0277 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 4802 2 ffff88003d613180 0          
  470: 076A070A:007B 00000000:0000 07 FFFF4600:00000000 00:00000000 00000000   123        0 5552 2 ffff880039974380 0          
  470: 010213AC:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 4986 2 ffff88003dbd3180 0          
  470: 010013AC:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 4985 2 ffff88003dbd2e00 0          
  470: 00FCA8C0:007B 00000000:0000 07 FFFFFB00:00000000 00:00000000 00000000     0        0 4984 2 ffff88003dbd2a80 0        
...

Playing with skb->truesize is tricky, especially when
skb is attached to a socket, as we can fool memory charging.

Just remove this code, its not worth trying to be ultra
precise in xmit path.

Reported-by: Andrew Savchenko <bircoph@gmail.com>
Tested-by: Andrew Savchenko <bircoph@gmail.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: James Chapman <jchapman@katalix.com>
---
 net/l2tp/l2tp_core.c |    6 ------
 net/l2tp/l2tp_ppp.c  |    6 ------
 2 files changed, 12 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 06389d5..2ac884d 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1168,8 +1168,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
 	struct udphdr *uh;
 	struct inet_sock *inet;
 	__wsum csum;
-	int old_headroom;
-	int new_headroom;
 	int headroom;
 	int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
 	int udp_len;
@@ -1181,16 +1179,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
 	 */
 	headroom = NET_SKB_PAD + sizeof(struct iphdr) +
 		uhlen + hdr_len;
-	old_headroom = skb_headroom(skb);
 	if (skb_cow_head(skb, headroom)) {
 		kfree_skb(skb);
 		return NET_XMIT_DROP;
 	}
 
-	new_headroom = skb_headroom(skb);
 	skb_orphan(skb);
-	skb->truesize += new_headroom - old_headroom;
-
 	/* Setup L2TP header */
 	session->build_header(session, __skb_push(skb, hdr_len));
 
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 286366e..716605c 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -388,8 +388,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 	struct l2tp_session *session;
 	struct l2tp_tunnel *tunnel;
 	struct pppol2tp_session *ps;
-	int old_headroom;
-	int new_headroom;
 	int uhlen, headroom;
 
 	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
@@ -408,7 +406,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 	if (tunnel == NULL)
 		goto abort_put_sess;
 
-	old_headroom = skb_headroom(skb);
 	uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
 	headroom = NET_SKB_PAD +
 		   sizeof(struct iphdr) + /* IP header */
@@ -418,9 +415,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 	if (skb_cow_head(skb, headroom))
 		goto abort_put_sess_tun;
 
-	new_headroom = skb_headroom(skb);
-	skb->truesize += new_headroom - old_headroom;
-
 	/* Setup PPP header */
 	__skb_push(skb, sizeof(ppph));
 	skb->data[0] = ppph[0];

^ permalink raw reply related

* FedEx Post Await You
From: FEDEX COURIER SERVICE @ 2013-02-08  1:17 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 61 bytes --]


Please open the attachment and contact FedEx urgently.

 

[-- Attachment #2: fedex Confirmed Package.rtf --]
[-- Type: application/msword, Size: 597184 bytes --]

^ permalink raw reply

* Re: net: rcu warnings in ip6fl_get_first
From: Cong Wang @ 2013-02-08  1:37 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev
In-Reply-To: <51140154.9040901@oracle.com>

["Followup-To:" header set to gmane.linux.network.]
On Thu, 07 Feb 2013 at 19:32 GMT, Sasha Levin <sasha.levin@oracle.com> wrote:
> Hi guys,
>
> I got the following while fuzzing with trinity inside a KVM tools guest:
>
> [   51.680236] ===============================
> [   51.681914] [ INFO: suspicious RCU usage. ]
> [   51.683610] 3.8.0-rc6-next-20130206-sasha-00028-g83214f7-dirty #276 Tainted: G        W
> [   51.686703] -------------------------------
> [   51.688281] net/ipv6/ip6_flowlabel.c:671 suspicious rcu_dereference_check() usage!
> [   51.691345]
> [   51.691345] other info that might help us debug this:
> [   51.691345]
> [   51.694479]
> [   51.694479] rcu_scheduler_active = 1, debug_locks = 1
> [   51.697650] 2 locks held by trinity/7421:
> [   51.701271]  #0:  (&p->lock){+.+.+.}, at: [<ffffffff812b049a>] seq_read+0x3a/0x3d0
> [   51.704292]  #1:  (rcu_read_lock_bh){.+....}, at: [<ffffffff8397cde0>] ip6fl_seq_start+0x0/0xe0
> [   51.707845]
> [   51.707845] stack backtrace:
> [   51.709678] Pid: 7421, comm: trinity Tainted: G        W    3.8.0-rc6-next-20130206-sasha-00028-g83214f7-dirty #276
> [   51.713495] Call Trace:
> [   51.714370]  [<ffffffff81181fdb>] lockdep_rcu_suspicious+0x10b/0x120
> [   51.716560]  [<ffffffff8397caca>] ip6fl_get_first+0x8a/0x140
> [   51.718755]  [<ffffffff8397cdb7>] ip6fl_seq_next+0x17/0x40
> [   51.720963]  [<ffffffff812b0711>] seq_read+0x2b1/0x3d0
> [   51.723056]  [<ffffffff812b0460>] ? seq_lseek+0x110/0x110
> [   51.725238]  [<ffffffff812f9c0c>] proc_reg_read+0x9c/0xd0
> [   51.727266]  [<ffffffff812f9b70>] ? proc_reg_write+0xd0/0xd0
> [   51.729337]  [<ffffffff8128b2eb>] do_loop_readv_writev+0x4b/0x90
> [   51.731846]  [<ffffffff8128b566>] do_readv_writev+0xf6/0x1d0
> [   51.734092]  [<ffffffff8128b6de>] vfs_readv+0x3e/0x60
> [   51.736015]  [<ffffffff8128b750>] sys_readv+0x50/0xd0
> [   51.737930]  [<ffffffff83d73d98>] tracesys+0xe1/0xe6
>
> This is the result of commit "ipv6 flowlabel: Convert hash list to RCU." which
> mixes between regular and _bh() locking.
>
>
> Thanks,
> Sasha

^ permalink raw reply

* Re: net: rcu warnings in ip6fl_get_first
From: Cong Wang @ 2013-02-08  1:38 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel
In-Reply-To: <51140154.9040901@oracle.com>

On Thu, 07 Feb 2013 at 19:32 GMT, Sasha Levin <sasha.levin@oracle.com> wrote:
> Hi guys,
>
> I got the following while fuzzing with trinity inside a KVM tools guest:
>
> [   51.680236] ===============================
> [   51.681914] [ INFO: suspicious RCU usage. ]
> [   51.683610] 3.8.0-rc6-next-20130206-sasha-00028-g83214f7-dirty #276 Tainted: G        W
> [   51.686703] -------------------------------
> [   51.688281] net/ipv6/ip6_flowlabel.c:671 suspicious rcu_dereference_check() usage!
> [   51.691345]

It should use rcu_dereference_bh()...

diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index ea42bf4..c50080f 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -65,13 +65,13 @@ static DEFINE_SPINLOCK(ip6_fl_lock);
 static DEFINE_SPINLOCK(ip6_sk_fl_lock);
 
 #define for_each_fl_rcu(hash, fl)				\
-	for (fl = rcu_dereference(fl_ht[(hash)]);		\
+	for (fl = rcu_dereference_bh(fl_ht[(hash)]);		\
 	     fl != NULL;					\
-	     fl = rcu_dereference(fl->next))
+	     fl = rcu_dereference_hb(fl->next))
 #define for_each_fl_continue_rcu(fl)				\
-	for (fl = rcu_dereference(fl->next);			\
+	for (fl = rcu_dereference_bh(fl->next);			\
 	     fl != NULL;					\
-	     fl = rcu_dereference(fl->next))
+	     fl = rcu_dereference_bh(fl->next))
 
 #define for_each_sk_fl_rcu(np, sfl)				\
 	for (sfl = rcu_dereference_bh(np->ipv6_fl_list);	\

^ permalink raw reply related

* [Patch net-next] ipv6: fix a RCU warning in net/ipv6/ip6_flowlabel.c
From: Cong Wang @ 2013-02-08  1:52 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, YOSHIFUJI Hideaki, Cong Wang

This patch fixes the following RCU warning:

[   51.680236] ===============================
[   51.681914] [ INFO: suspicious RCU usage. ]
[   51.683610] 3.8.0-rc6-next-20130206-sasha-00028-g83214f7-dirty #276 Tainted: G        W
[   51.686703] -------------------------------
[   51.688281] net/ipv6/ip6_flowlabel.c:671 suspicious rcu_dereference_check() usage!

we should use rcu_dereference_bh() when we hold rcu_read_lock_bh().

Reported-by: Sasha Levin <sasha.levin@oracle.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Cong Wang <amwang@redhat.com>

---
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index ea42bf4..a7da2f4 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -65,13 +65,13 @@ static DEFINE_SPINLOCK(ip6_fl_lock);
 static DEFINE_SPINLOCK(ip6_sk_fl_lock);
 
 #define for_each_fl_rcu(hash, fl)				\
-	for (fl = rcu_dereference(fl_ht[(hash)]);		\
+	for (fl = rcu_dereference_bh(fl_ht[(hash)]);		\
 	     fl != NULL;					\
-	     fl = rcu_dereference(fl->next))
+	     fl = rcu_dereference_bh(fl->next))
 #define for_each_fl_continue_rcu(fl)				\
-	for (fl = rcu_dereference(fl->next);			\
+	for (fl = rcu_dereference_bh(fl->next);			\
 	     fl != NULL;					\
-	     fl = rcu_dereference(fl->next))
+	     fl = rcu_dereference_bh(fl->next))
 
 #define for_each_sk_fl_rcu(np, sfl)				\
 	for (sfl = rcu_dereference_bh(np->ipv6_fl_list);	\

^ permalink raw reply related

* [PATCH net-next] macvlan: broadcast addr should be part of mc_filter
From: Eric Dumazet @ 2013-02-08  2:02 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Maciej Żenczykowski

From: Eric Dumazet <edumazet@google.com>

commit cd431e738509e (macvlan: add multicast filter) forgot
the broadcast case.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Maciej Żenczykowski <maze@google.com>
---
 drivers/net/macvlan.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index f494da8..ce7c926 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -426,6 +426,9 @@ static void macvlan_set_mac_lists(struct net_device *dev)
 		netdev_for_each_mc_addr(ha, dev) {
 			__set_bit(mc_hash(ha->addr), filter);
 		}
+
+		__set_bit(mc_hash(dev->broadcast), filter);
+
 		bitmap_copy(vlan->mc_filter, filter, MACVLAN_MC_FILTER_SZ);
 	}
 	dev_uc_sync(vlan->lowerdev, dev);

^ permalink raw reply related

* Re: [PATCH net-next] macvlan: broadcast addr should be part of mc_filter
From: Maciej Żenczykowski @ 2013-02-08  2:05 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1360288977.28557.77.camel@edumazet-glaptop>

SIgned-off-by: Maciej Żenczykowski <maze@google.com>

On Thu, Feb 7, 2013 at 6:02 PM, Eric Dumazet <erdnetdev@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> commit cd431e738509e (macvlan: add multicast filter) forgot
> the broadcast case.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: Maciej Żenczykowski <maze@google.com>
> ---
>  drivers/net/macvlan.c |    3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index f494da8..ce7c926 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -426,6 +426,9 @@ static void macvlan_set_mac_lists(struct net_device *dev)
>                 netdev_for_each_mc_addr(ha, dev) {
>                         __set_bit(mc_hash(ha->addr), filter);
>                 }
> +
> +               __set_bit(mc_hash(dev->broadcast), filter);
> +
>                 bitmap_copy(vlan->mc_filter, filter, MACVLAN_MC_FILTER_SZ);
>         }
>         dev_uc_sync(vlan->lowerdev, dev);
>
>

^ permalink raw reply

* [PATCH] net: usb: fix regression from 6509141f9c2ba74df6cc72ec35cd1865276ae3a4
From: Lucas Stach @ 2013-02-08  2:18 UTC (permalink / raw)
  To: netdev; +Cc: Wei Shuai, David S. Miller

The newly added flag NOARP was using an already defined value, which
broke drivers using flag MULTI_PACKET.

Signed-off-by: Lucas Stach <dev@lynxeye.de>
---
As the regressing patch went in with v3.8-rc5, this fix should go to
mainline ASAP.
---
 include/linux/usb/usbnet.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 5de7a22..2cb5fb6 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -100,7 +100,6 @@ struct driver_info {
 #define FLAG_LINK_INTR	0x0800		/* updates link (carrier) status */
 
 #define FLAG_POINTTOPOINT 0x1000	/* possibly use "usb%d" names */
-#define FLAG_NOARP	0x2000		/* device can't do ARP */
 
 /*
  * Indicates to usbnet, that USB driver accumulates multiple IP packets.
@@ -108,6 +107,7 @@ struct driver_info {
  */
 #define FLAG_MULTI_PACKET	0x2000
 #define FLAG_RX_ASSEMBLE	0x4000	/* rx packets may span >1 frames */
+#define FLAG_NOARP		0x8000	/* device can't do ARP */
 
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
-- 
1.8.1

^ permalink raw reply related

* Re: splice() giving unexpected EOF in 3.7.3 and 3.8-rc4+
From: Eric Wong @ 2013-02-08  2:39 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, linux-kernel, netdev, linux-fsdevel, w
In-Reply-To: <20130120.232122.1798689273842981732.davem@davemloft.net>

David Miller <davem@davemloft.net> wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 18 Jan 2013 22:13:16 -0800
> 
> > On Fri, 2013-01-18 at 21:54 -0800, Eric Dumazet wrote:
> > 
> >> 
> >> Hmm, this might be already fixed in net-next tree, could you try it ?
> >> 
> > 
> > Yes, running your program on net-next seems OK.
> > 
> > David, we need the two following commits.
> 
> Tossed into 'net' and queued up for -stable, thanks.

Hi David, any update on getting these into -stable?  Thanks.

^ permalink raw reply

* [PATCH net-next] macvlan: add a salt to mc_hash()
From: Eric Dumazet @ 2013-02-08  2:41 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Maciej Żenczykowski

From: Eric Dumazet <edumazet@google.com>

Some multicast addresses are common to all macvlans,
so if a multicast message has a hash value collision, we
have to deliver a copy to all macvlans, adding significant
latency and possible packet drops if netdev_max_backlog
limit is hit.

Having a per macvlan hash function permits to reduce the
impact of hash collisions.

Suggested-by: Maciej Żenczykowski <maze@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
Should be applied after 
  "macvlan: broadcast addr should be part of mc_filter"

 drivers/net/macvlan.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ce7c926..e4b8078 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -127,10 +127,18 @@ static int macvlan_broadcast_one(struct sk_buff *skb,
 	return vlan->receive(skb);
 }
 
-static unsigned int mc_hash(const unsigned char *addr)
+static u32 macvlan_hash_mix(const struct macvlan_dev *vlan)
+{
+	return (u32)(((unsigned long)vlan) >> L1_CACHE_SHIFT);
+}
+
+
+static unsigned int mc_hash(const struct macvlan_dev *vlan,
+			    const unsigned char *addr)
 {
 	u32 val = __get_unaligned_cpu32(addr + 2);
 
+	val ^= macvlan_hash_mix(vlan);
 	return hash_32(val, MACVLAN_MC_FILTER_BITS);
 }
 
@@ -145,7 +153,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
 	struct sk_buff *nskb;
 	unsigned int i;
 	int err;
-	unsigned int hash = mc_hash(eth->h_dest);
+	unsigned int hash;
 
 	if (skb->protocol == htons(ETH_P_PAUSE))
 		return;
@@ -155,6 +163,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
 			if (vlan->dev == src || !(vlan->mode & mode))
 				continue;
 
+			hash = mc_hash(vlan, eth->h_dest);
 			if (!test_bit(hash, vlan->mc_filter))
 				continue;
 			nskb = skb_clone(skb, GFP_ATOMIC);
@@ -424,10 +433,10 @@ static void macvlan_set_mac_lists(struct net_device *dev)
 
 		bitmap_zero(filter, MACVLAN_MC_FILTER_SZ);
 		netdev_for_each_mc_addr(ha, dev) {
-			__set_bit(mc_hash(ha->addr), filter);
+			__set_bit(mc_hash(vlan, ha->addr), filter);
 		}
 
-		__set_bit(mc_hash(dev->broadcast), filter);
+		__set_bit(mc_hash(vlan, dev->broadcast), filter);
 
 		bitmap_copy(vlan->mc_filter, filter, MACVLAN_MC_FILTER_SZ);
 	}

^ permalink raw reply related

* Re: [PATCH] netpoll: cleanup sparse warnings
From: Eric Dumazet @ 2013-02-08  3:25 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, fengguang.wu, David Miller
In-Reply-To: <20130207183725.GE2379@shamino.rdu.redhat.com>

On Thu, 2013-02-07 at 13:37 -0500, Neil Horman wrote:
> On Thu, Feb 07, 2013 at 07:52:56AM -0800, Eric Dumazet wrote:
> > On Thu, 2013-02-07 at 09:56 -0500, Neil Horman wrote:
> > > With my recent commit I introduced two sparse warnings.  Looking closer there
> > > were a few more in the same file, so I fixed them all up.  Basic rcu pointer
> > > dereferencing suff
> > 
> > > -	npinfo = np->dev->npinfo;
> > > +	/* rtnl_dereference would be preferable here but
> > > +	 * rcu_cleanup_netpoll path can put us in here safely without
> > > +	 * holding the rtnl, so plain rcu_dereference it is
> > > +	 */
> > > +	npinfo = rcu_dereference(np->dev->npinfo);
> > >  	if (!npinfo)
> > >  		return;
> > >  
> > 
> > Are you sure it wont trigger a LOCKDEP complain (CONFIG_PROVE_RCU=y) ?
> > 
> Hm, looking at it, you're probably right.  We're not holding the rcu_read_lock,
> and I'd forgotten that rcu_dereference implicitly checks that rcu_read_lock is
> held.  I guess, since the only paths that we get here on are in a bh rcu
> quiescence point or with the rtnl held we should probably make this:
> 
> rcu_dereference_protected(np->dev->npinfo, rtnl_locked() || in_interrupt());
> 
> Although, thinking about this further somewhat begs the question as to how we
> prevent one context from calling __netpoll_cleanup in a path holding rtnl, while
> in parallel calling __netpoll_cleanup from the rcu callback.  That might not be
> a huge deal as __netpoll_cleanup uses spinlocks to do list modification, and an
> atomic_dec_and_test to gate the free, but it still seems ugly.
> 
> What do you think?

I think you could use 

 rcu_dereference_check(p, lockdep_rtnl_is_held() || something)

^ permalink raw reply

* Re: splice() giving unexpected EOF in 3.7.3 and 3.8-rc4+
From: David Miller @ 2013-02-08  3:26 UTC (permalink / raw)
  To: normalperson; +Cc: eric.dumazet, linux-kernel, netdev, linux-fsdevel, w
In-Reply-To: <20130208023946.GA23197@dcvr.yhbt.net>

From: Eric Wong <normalperson@yhbt.net>
Date: Fri, 8 Feb 2013 02:39:46 +0000

> David Miller <davem@davemloft.net> wrote:
>> From: Eric Dumazet <eric.dumazet@gmail.com>
>> Date: Fri, 18 Jan 2013 22:13:16 -0800
>> 
>> > On Fri, 2013-01-18 at 21:54 -0800, Eric Dumazet wrote:
>> > 
>> >> 
>> >> Hmm, this might be already fixed in net-next tree, could you try it ?
>> >> 
>> > 
>> > Yes, running your program on net-next seems OK.
>> > 
>> > David, we need the two following commits.
>> 
>> Tossed into 'net' and queued up for -stable, thanks.
> 
> Hi David, any update on getting these into -stable?  Thanks.

I submit stable patches once they have cooked upstream for
a week or two.

^ permalink raw reply

* Re: [PATCH, resubmit] ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver
From: Freddy @ 2013-02-08  3:41 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, davem, linux-usb, linux-kernel
In-Reply-To: <1360267375.3605.32.camel@bwh-desktop.uk.solarflarecom.com>

On 02/08/2013 04:02 AM, Ben Hutchings wrote:
> On Thu, 2013-02-07 at 21:39 +0800, Freddy Xin wrote:
>> From: Freddy Xin <freddy@asix.com.tw>
>>
>> This is a resubmission.
>> Added "const" to ethtool_ops structure and fixed the coding style of AX88179_BULKIN_SIZE array.
>> Fixed the issue that the default MTU is not 1500.
>> Added ax88179_change_mtu function and enabled the hardware jumbo frame function to support an
>> MTU higher than 1500.
>> Fixed indentation and empty line coding style errors.
>> The _nopm version usb functions were added to access register in suspend and resume functions.
>> Serveral variables allocted dynamically were removed and replaced by stack variables.
>> ax88179_get_eeprom were modified from asix_get_eeprom in asix_common.
>>
>> This patch adds a driver for ASIX's AX88179 family of USB 3.0/2.0
>> to gigabit ethernet adapters. It's based on the AX88xxx driver but
>> the usb commands used to access registers for AX88179 are completely different.
>> This driver had been verified on x86 system with AX88179/AX88178A and
>> Sitcomm LN-032 USB dongles.
>>
>> Signed-off-by: Freddy Xin <freddy@asix.com.tw>
> [...]
>> --- /dev/null
>> +++ b/drivers/net/usb/ax88179_178a.c
> [...]
>> +struct ax88179_data {
>> +       u16 rxctl;
>> +};
> Should also be declared __packed, as on some architectures it may be
> padded to 4 bytes.
>
> rxctl is presumably required to be little-endian (__le16)?
>
>> +struct ax88179_int_data {
>> +       u16 res1;
>> +       u8 link;
>> +       u16 res2;
>> +       u8 status;
>> +       u16 res3;
>> +} __packed;
> Same here, the u16 fields are presumably little-endian?
>
> [...]
>> +struct ax88179_rx_pkt_header {
>> +	u8	l4_csum_err:1,
>> +		l3_csum_err:1,
>> +		l4_type:3,
>> +		l3_type:2,
>> +		ce:1;
>> +
>> +	u8	vlan_ind:3,
>> +		rx_ok:1,
>> +		pri:3,
>> +		bmc:1;
>> +
>> +	u16	len:13,
>> +		crc:1,
>> +		mii:1,
>> +		drop:1;
>> +} __packed;
> This won't work on both big-endian systems (assuming this works on x86).
> You apparently try to convert the structure in-place in
> ax88179_rx_fixup() by calling le32_to_cpus(); that may work if you
> define all the bitfields to be part of a u32 but it won't work with the
> current definition.
>
> [...]
>> +static int
>> +ax88179_set_features(struct net_device *net, netdev_features_t features)
>> +{
>> +	u8 tmp;
>> +	struct usbnet *dev = netdev_priv(net);
>> +	netdev_features_t changed = net->features ^ features;
>> +
>> +	if (changed & NETIF_F_TSO)
>> +		net->features ^= NETIF_F_TSO;
>> +
>> +	if (changed & NETIF_F_SG)
>> +		net->features ^= NETIF_F_SG;
> Don't change net->features; the caller will do that for you.
>
>> +       if (changed & NETIF_F_IP_CSUM) {
>> +               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
>> +               tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP;
>> +               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
>> +
>> +               net->features ^= NETIF_F_IP_CSUM;
>> +       }
> [...]
>
> Isn't tmp going to be in little-endian byte order, so this doesn't work
> correctly on a big-endian system?
>
> There are a lot of reads and writes of 16-bit registers using
> ax88179_{read,write}_cmd(); maybe you should add
> ax88179_{read,write}_le16() to handle this specific case.
>
> Ben.
>
Thank you, Ben. I will fix bugs and test it on a big-endian system.

Freddy

^ permalink raw reply

* Re: net: rcu warnings in ip6fl_get_first
From: Sasha Levin @ 2013-02-08  3:54 UTC (permalink / raw)
  To: Cong Wang; +Cc: linux-kernel, netdev, davem, yoshfuji
In-Reply-To: <kf1kul$699$2@ger.gmane.org>

On Thu, Feb 7, 2013 at 8:38 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Thu, 07 Feb 2013 at 19:32 GMT, Sasha Levin <sasha.levin@oracle.com> wrote:
>> Hi guys,
>>
>> I got the following while fuzzing with trinity inside a KVM tools guest:
>>
>> [   51.680236] ===============================
>> [   51.681914] [ INFO: suspicious RCU usage. ]
>> [   51.683610] 3.8.0-rc6-next-20130206-sasha-00028-g83214f7-dirty #276 Tainted: G        W
>> [   51.686703] -------------------------------
>> [   51.688281] net/ipv6/ip6_flowlabel.c:671 suspicious rcu_dereference_check() usage!
>> [   51.691345]
>
> It should use rcu_dereference_bh()...
>
> diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
> index ea42bf4..c50080f 100644
> --- a/net/ipv6/ip6_flowlabel.c
> +++ b/net/ipv6/ip6_flowlabel.c
> @@ -65,13 +65,13 @@ static DEFINE_SPINLOCK(ip6_fl_lock);
>  static DEFINE_SPINLOCK(ip6_sk_fl_lock);
>
>  #define for_each_fl_rcu(hash, fl)                              \
> -       for (fl = rcu_dereference(fl_ht[(hash)]);               \
> +       for (fl = rcu_dereference_bh(fl_ht[(hash)]);            \
>              fl != NULL;                                        \
> -            fl = rcu_dereference(fl->next))
> +            fl = rcu_dereference_hb(fl->next))
>  #define for_each_fl_continue_rcu(fl)                           \
> -       for (fl = rcu_dereference(fl->next);                    \
> +       for (fl = rcu_dereference_bh(fl->next);                 \
>              fl != NULL;                                        \
> -            fl = rcu_dereference(fl->next))
> +            fl = rcu_dereference_bh(fl->next))
>
>  #define for_each_sk_fl_rcu(np, sfl)                            \
>         for (sfl = rcu_dereference_bh(np->ipv6_fl_list);        \

Yup, that's how I fixed it locally and it was running without warnings
for couple of hours now.


Thanks,
Sasha

^ permalink raw reply

* [PATCH RFC v2 2/2] net/8021q: Implement Multiple VLAN Registration Protocol (MVRP)
From: David Ward @ 2013-02-08  3:50 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy, Eric Dumazet, David Ward
In-Reply-To: <1360295457-5245-1-git-send-email-david.ward@ll.mit.edu>

Initial implementation of the Multiple VLAN Registration Protocol
(MVRP) from IEEE 802.1Q-2011, based on the existing implementation
of the GARP VLAN Registration Protocol (GVRP).

Signed-off-by: David Ward <david.ward@ll.mit.edu>
---
 include/uapi/linux/if_ether.h |    1 +
 include/uapi/linux/if_vlan.h  |    1 +
 net/8021q/Kconfig             |   11 ++++++
 net/8021q/Makefile            |    1 +
 net/8021q/vlan.c              |   27 ++++++++++++---
 net/8021q/vlan.h              |   16 +++++++++
 net/8021q/vlan_dev.c          |   12 ++++++-
 net/8021q/vlan_mvrp.c         |   72 +++++++++++++++++++++++++++++++++++++++++
 net/8021q/vlan_netlink.c      |    2 +-
 9 files changed, 136 insertions(+), 7 deletions(-)
 create mode 100644 net/8021q/vlan_mvrp.c

diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 67fb87c..798032d 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -83,6 +83,7 @@
 #define ETH_P_802_EX1	0x88B5		/* 802.1 Local Experimental 1.  */
 #define ETH_P_TIPC	0x88CA		/* TIPC 			*/
 #define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
+#define ETH_P_MVRP	0x88F5          /* 802.1Q MVRP                  */
 #define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
 #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
 #define ETH_P_TDLS	0x890D          /* TDLS */
diff --git a/include/uapi/linux/if_vlan.h b/include/uapi/linux/if_vlan.h
index 0744f8e..7e5e6b3 100644
--- a/include/uapi/linux/if_vlan.h
+++ b/include/uapi/linux/if_vlan.h
@@ -34,6 +34,7 @@ enum vlan_flags {
 	VLAN_FLAG_REORDER_HDR	= 0x1,
 	VLAN_FLAG_GVRP		= 0x2,
 	VLAN_FLAG_LOOSE_BINDING	= 0x4,
+	VLAN_FLAG_MVRP		= 0x8,
 };
 
 enum vlan_name_types {
diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig
index fa073a5..8f7517d 100644
--- a/net/8021q/Kconfig
+++ b/net/8021q/Kconfig
@@ -27,3 +27,14 @@ config VLAN_8021Q_GVRP
 	  automatic propagation of registered VLANs to switches.
 
 	  If unsure, say N.
+
+config VLAN_8021Q_MVRP
+	bool "MVRP (Multiple VLAN Registration Protocol) support"
+	depends on VLAN_8021Q
+	select MRP
+	help
+	  Select this to enable MVRP end-system support. MVRP is used for
+	  automatic propagation of registered VLANs to switches; it
+	  supersedes GVRP and is not backwards-compatible.
+
+	  If unsure, say N.
diff --git a/net/8021q/Makefile b/net/8021q/Makefile
index 9f4f174..7bc8db0 100644
--- a/net/8021q/Makefile
+++ b/net/8021q/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_VLAN_8021Q)		+= 8021q.o
 
 8021q-y					:= vlan.o vlan_dev.o vlan_netlink.o
 8021q-$(CONFIG_VLAN_8021Q_GVRP)		+= vlan_gvrp.o
+8021q-$(CONFIG_VLAN_8021Q_MVRP)		+= vlan_mvrp.o
 8021q-$(CONFIG_PROC_FS)			+= vlanproc.o
 
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index addc578..a187144 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -95,6 +95,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 
 	grp->nr_vlan_devs--;
 
+	if (vlan->flags & VLAN_FLAG_MVRP)
+		vlan_mvrp_request_leave(dev);
 	if (vlan->flags & VLAN_FLAG_GVRP)
 		vlan_gvrp_request_leave(dev);
 
@@ -107,8 +109,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 
 	netdev_upper_dev_unlink(real_dev, dev);
 
-	if (grp->nr_vlan_devs == 0)
+	if (grp->nr_vlan_devs == 0) {
+		vlan_mvrp_uninit_applicant(real_dev);
 		vlan_gvrp_uninit_applicant(real_dev);
+	}
 
 	/* Get rid of the vlan's reference to real_dev */
 	dev_put(real_dev);
@@ -151,15 +155,18 @@ int register_vlan_dev(struct net_device *dev)
 		err = vlan_gvrp_init_applicant(real_dev);
 		if (err < 0)
 			goto out_vid_del;
+		err = vlan_mvrp_init_applicant(real_dev);
+		if (err < 0)
+			goto out_uninit_gvrp;
 	}
 
 	err = vlan_group_prealloc_vid(grp, vlan_id);
 	if (err < 0)
-		goto out_uninit_applicant;
+		goto out_uninit_mvrp;
 
 	err = netdev_upper_dev_link(real_dev, dev);
 	if (err)
-		goto out_uninit_applicant;
+		goto out_uninit_mvrp;
 
 	err = register_netdevice(dev);
 	if (err < 0)
@@ -181,7 +188,10 @@ int register_vlan_dev(struct net_device *dev)
 
 out_upper_dev_unlink:
 	netdev_upper_dev_unlink(real_dev, dev);
-out_uninit_applicant:
+out_uninit_mvrp:
+	if (grp->nr_vlan_devs == 0)
+		vlan_mvrp_uninit_applicant(real_dev);
+out_uninit_gvrp:
 	if (grp->nr_vlan_devs == 0)
 		vlan_gvrp_uninit_applicant(real_dev);
 out_vid_del:
@@ -655,13 +665,19 @@ static int __init vlan_proto_init(void)
 	if (err < 0)
 		goto err3;
 
-	err = vlan_netlink_init();
+	err = vlan_mvrp_init();
 	if (err < 0)
 		goto err4;
 
+	err = vlan_netlink_init();
+	if (err < 0)
+		goto err5;
+
 	vlan_ioctl_set(vlan_ioctl_handler);
 	return 0;
 
+err5:
+	vlan_mvrp_uninit();
 err4:
 	vlan_gvrp_uninit();
 err3:
@@ -682,6 +698,7 @@ static void __exit vlan_cleanup_module(void)
 	unregister_pernet_subsys(&vlan_net_ops);
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 
+	vlan_mvrp_uninit();
 	vlan_gvrp_uninit();
 }
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index a4886d9..670f1e8 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -171,6 +171,22 @@ static inline int vlan_gvrp_init(void) { return 0; }
 static inline void vlan_gvrp_uninit(void) {}
 #endif
 
+#ifdef CONFIG_VLAN_8021Q_MVRP
+extern int vlan_mvrp_request_join(const struct net_device *dev);
+extern void vlan_mvrp_request_leave(const struct net_device *dev);
+extern int vlan_mvrp_init_applicant(struct net_device *dev);
+extern void vlan_mvrp_uninit_applicant(struct net_device *dev);
+extern int vlan_mvrp_init(void);
+extern void vlan_mvrp_uninit(void);
+#else
+static inline int vlan_mvrp_request_join(const struct net_device *dev) { return 0; }
+static inline void vlan_mvrp_request_leave(const struct net_device *dev) {}
+static inline int vlan_mvrp_init_applicant(struct net_device *dev) { return 0; }
+static inline void vlan_mvrp_uninit_applicant(struct net_device *dev) {}
+static inline int vlan_mvrp_init(void) { return 0; }
+static inline void vlan_mvrp_uninit(void) {}
+#endif
+
 extern const char vlan_fullname[];
 extern const char vlan_version[];
 extern int vlan_netlink_init(void);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 09f9108..34df5b3 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -261,7 +261,7 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
 	u32 old_flags = vlan->flags;
 
 	if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
-		     VLAN_FLAG_LOOSE_BINDING))
+		     VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
 		return -EINVAL;
 
 	vlan->flags = (old_flags & ~mask) | (flags & mask);
@@ -272,6 +272,13 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
 		else
 			vlan_gvrp_request_leave(dev);
 	}
+
+	if (netif_running(dev) && (vlan->flags ^ old_flags) & VLAN_FLAG_MVRP) {
+		if (vlan->flags & VLAN_FLAG_MVRP)
+			vlan_mvrp_request_join(dev);
+		else
+			vlan_mvrp_request_leave(dev);
+	}
 	return 0;
 }
 
@@ -312,6 +319,9 @@ static int vlan_dev_open(struct net_device *dev)
 	if (vlan->flags & VLAN_FLAG_GVRP)
 		vlan_gvrp_request_join(dev);
 
+	if (vlan->flags & VLAN_FLAG_MVRP)
+		vlan_mvrp_request_join(dev);
+
 	if (netif_carrier_ok(real_dev))
 		netif_carrier_on(dev);
 	return 0;
diff --git a/net/8021q/vlan_mvrp.c b/net/8021q/vlan_mvrp.c
new file mode 100644
index 0000000..d9ec1d5
--- /dev/null
+++ b/net/8021q/vlan_mvrp.c
@@ -0,0 +1,72 @@
+/*
+ *	IEEE 802.1Q Multiple VLAN Registration Protocol (MVRP)
+ *
+ *	Copyright (c) 2012 Massachusetts Institute of Technology
+ *
+ *	Adapted from code in net/8021q/vlan_gvrp.c
+ *	Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	version 2 as published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <net/mrp.h>
+#include "vlan.h"
+
+#define MRP_MVRP_ADDRESS	{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 }
+
+enum mvrp_attributes {
+	MVRP_ATTR_INVALID,
+	MVRP_ATTR_VID,
+	__MVRP_ATTR_MAX
+};
+#define MVRP_ATTR_MAX	(__MVRP_ATTR_MAX - 1)
+
+static struct mrp_application vlan_mrp_app __read_mostly = {
+	.type		= MRP_APPLICATION_MVRP,
+	.maxattr	= MVRP_ATTR_MAX,
+	.pkttype.type	= htons(ETH_P_MVRP),
+	.group_address	= MRP_MVRP_ADDRESS,
+	.version	= 0,
+};
+
+int vlan_mvrp_request_join(const struct net_device *dev)
+{
+	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+	__be16 vlan_id = htons(vlan->vlan_id);
+
+	return mrp_request_join(vlan->real_dev, &vlan_mrp_app,
+				&vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
+}
+
+void vlan_mvrp_request_leave(const struct net_device *dev)
+{
+	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+	__be16 vlan_id = htons(vlan->vlan_id);
+
+	mrp_request_leave(vlan->real_dev, &vlan_mrp_app,
+			  &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
+}
+
+int vlan_mvrp_init_applicant(struct net_device *dev)
+{
+	return mrp_init_applicant(dev, &vlan_mrp_app);
+}
+
+void vlan_mvrp_uninit_applicant(struct net_device *dev)
+{
+	mrp_uninit_applicant(dev, &vlan_mrp_app);
+}
+
+int __init vlan_mvrp_init(void)
+{
+	return mrp_register_application(&vlan_mrp_app);
+}
+
+void vlan_mvrp_uninit(void)
+{
+	mrp_unregister_application(&vlan_mrp_app);
+}
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 708c80e..1789658 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -62,7 +62,7 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
 		flags = nla_data(data[IFLA_VLAN_FLAGS]);
 		if ((flags->flags & flags->mask) &
 		    ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
-		      VLAN_FLAG_LOOSE_BINDING))
+		      VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
 			return -EINVAL;
 	}
 
-- 
1.7.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox