Netdev List
 help / color / mirror / Atom feed
* Re: compound skb frag pages appearing in start_xmit
From: Ian Campbell @ 2012-10-09 14:54 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Eric Dumazet, xen-devel, netdev@vger.kernel.org,
	Konrad Rzeszutek Wilk, Sander Eikelenboom
In-Reply-To: <1349793217.21172.4497.camel@edumazet-glaptop>

On Tue, 2012-10-09 at 15:33 +0100, Eric Dumazet wrote:
> On Tue, 2012-10-09 at 15:23 +0100, Ian Campbell wrote:
> > On Tue, 2012-10-09 at 15:01 +0100, Eric Dumazet wrote:
> > > On Tue, 2012-10-09 at 15:54 +0200, Eric Dumazet wrote:
> > > > On Tue, 2012-10-09 at 14:47 +0100, Ian Campbell wrote:
> > > > > Hi Eric,
> > > > > 
> > > > 
> > > > Hi Ian
> > > > 
> > > > > Sander has discovered an issue where xen-netback is given a compound
> > > > > page as one of the skb frag pages to transmit. Currently netback can
> > > > > only handle PAGE_SIZE'd frags and bugs out.
> > > > > 
> > > > > I suspect this is something to do with 69b08f62e174 "net: use bigger
> > > > > pages in __netdev_alloc_frag", although perhaps not because it looks
> > > > > like only tg3 uses it and Sander has an r8169. Also tg3 seems to only
> > > > > call netdev_alloc_frag for sizes < PAGE_SIZE. I'm probably missing
> > > > > something.
> > > > 
> > > > 
> > > > Its not the commit you want ;)
> > > 
> > > Hmm, I take it back. It also can give you the same problem :
> > > 
> > > We use this allocator for rx path of drivers : 
> > > 
> > >  __netdev_alloc_skb() 
> > > 
> > > So its now absolutely possible that one skb->head is backed by a order-3
> > > page.
> > > 
> > > Is the problem coming from xen_netbk_count_skb_slots() ?
> > > 
> > > Give me more information if you want me to help.
> > 
> > The interesting code is in netbk_gop_skb(), specifically the two calls
> > to netbk_gop_frag_copy.
> > 
> > netbk_gop_frag_copy can only copy order-0 pages to the peer since they
> > go over a shared ring transport which can only deal in order-0 pages.
> > 
> > For the SKB head there is a loop which handles order>0 heads, I suspect
> > we just need something similar for the frag case.
> > 
> > Although see my question in the other response about the maximum number
> > of frags we can have when order is > 0 since if using larger pages
> > causes us to end up with a much larger number of order-0 pages once
> > we've broken them up then we have a problem and I need to put my
> > thinking cap on a bit (perhaps substantially) tighter.
> > 
> > Konrad, it looks like netfront has a similar issue in
> > xennet_make_frags() since it doesn't shatter large order mappings
> > either.
> 
> Hmm...
> 
> In theory, if a skb has 16+1 frags backed by compound pages, you could
> need ~48 order-0 frags.
> 
> (4098 bytes could need 1-4096-1 (3 frags))
> 
> In practice, it should be around ~17 order-0 frags as before.

Right, thanks. I think I can cope with that without needing to change
the PV protocol in any way.

Ian.

^ permalink raw reply

* [PATCH V1 0/3] net/mlx4: HW timestamping support
From: Or Gerlitz @ 2012-10-09 15:20 UTC (permalink / raw)
  To: davem; +Cc: netdev, Or Gerlitz, Richard Cochran, Eugenia Emantayev

This series of patches introduces Ethernet HW timestamping support in the mlx4 driver.

changes from v0:

- accept HWTSTAMP_FILTER_PTP_ and HWTSTAMP_FILTER_SOME flags but 
  reply with HWTSTAMP_FILTER_ALL
- remove usage of the timecompare API
- call netdev_features_change() after changing dev->features

Dave, the submission/review of this series begun before net-next
got closed, so we continue now that for the sake of getting feedback 
of the comments that were addressed and hopefully acceptance...

When RX/TX is enabled every incoming/outgoing packet will be timestamped.

The series is made of of three patches

1. Add timestamping device capability

2. Read HCA frequency and map internal clock

3. Add HW timestamping (TS) support --  Enable/disable HW timestamping 
for incoming and/or outgoing packets. Add and initialize all structs and 
callbacks needed by the kernel timestamping API.

The patches provide raw HW timestamps, where registeration in the 
driver as PHC class device will be done in a 2nd step, once the basic 
code is merged.

Or.


Eugenia Emantayev (3):
  net/mlx4_core: Add timestamping device capability
  net/mlx4_core: Read HCA frequency and map internal clock
  net/mlx4_en: Add HW timestamping (TS) support

 drivers/infiniband/hw/mlx4/cq.c                   |    2 +-
 drivers/net/ethernet/mellanox/mlx4/Makefile       |    2 +-
 drivers/net/ethernet/mellanox/mlx4/cq.c           |   10 +-
 drivers/net/ethernet/mellanox/mlx4/en_cq.c        |   10 ++-
 drivers/net/ethernet/mellanox/mlx4/en_main.c      |    5 +
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c    |   75 +++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_resources.c |    3 +
 drivers/net/ethernet/mellanox/mlx4/en_rx.c        |   28 ++++-
 drivers/net/ethernet/mellanox/mlx4/en_timestamp.c |  136 +++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_tx.c        |   31 +++++-
 drivers/net/ethernet/mellanox/mlx4/fw.c           |   18 +++-
 drivers/net/ethernet/mellanox/mlx4/fw.h           |    1 +
 drivers/net/ethernet/mellanox/mlx4/main.c         |   80 ++++++++++++
 drivers/net/ethernet/mellanox/mlx4/mlx4.h         |    6 +-
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h      |   17 +++
 include/linux/mlx4/cq.h                           |   16 +++
 include/linux/mlx4/device.h                       |   10 ++-
 17 files changed, 431 insertions(+), 19 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlx4/en_timestamp.c

Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Eugenia Emantayev <eugenia@mellanox.com>

^ permalink raw reply

* [PATCH V1 3/3] net/mlx4_en: Add HW timestamping (TS) support
From: Or Gerlitz @ 2012-10-09 15:20 UTC (permalink / raw)
  To: davem; +Cc: netdev, Eugenia Emantayev, Or Gerlitz
In-Reply-To: <1349796013-31106-1-git-send-email-ogerlitz@mellanox.com>

From: Eugenia Emantayev <eugenia@mellanox.com>

Enable/disable HW timestamping for incoming and/or outgoing packets.

Add and initialize all structs and callbacks needed by the kernel
timestamping API. To enable/disable HW timestamping, appropriate
ioctl should be used. Currently HWTSTAMP_FILTER_ALL/NONE and
HWTSAMP_TX_ON/OFF are supported.

When enabling TS on receive flow - VLAN stripping will be disabled.

Also made all relevant changes in RX/TX flows to consider TS request
and plant HW timestamps into relevant structures. The mlx4_ib driver
was modified to work with the new signature of mlx4_cq_alloc().

Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com>
Reviewed-by: Yevgeny Petrilin <yevgenyp@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 drivers/infiniband/hw/mlx4/cq.c                   |    2 +-
 drivers/net/ethernet/mellanox/mlx4/Makefile       |    2 +-
 drivers/net/ethernet/mellanox/mlx4/cq.c           |   10 +-
 drivers/net/ethernet/mellanox/mlx4/en_cq.c        |   10 ++-
 drivers/net/ethernet/mellanox/mlx4/en_main.c      |    5 +
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c    |   75 +++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_resources.c |    3 +
 drivers/net/ethernet/mellanox/mlx4/en_rx.c        |   28 ++++-
 drivers/net/ethernet/mellanox/mlx4/en_timestamp.c |  136 +++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_tx.c        |   31 +++++-
 drivers/net/ethernet/mellanox/mlx4/main.c         |   22 ++++
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h      |   17 +++
 include/linux/mlx4/cq.h                           |   16 +++
 include/linux/mlx4/device.h                       |    6 +-
 14 files changed, 347 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlx4/en_timestamp.c

diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index c9eb6a6..8fec4e1 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -226,7 +226,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
 		vector = dev->eq_table[vector % ibdev->num_comp_vectors];
 
 	err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
-			    cq->db.dma, &cq->mcq, vector, 0);
+			    cq->db.dma, &cq->mcq, vector, 0, 0);
 	if (err)
 		goto err_dbmap;
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/Makefile b/drivers/net/ethernet/mellanox/mlx4/Makefile
index 293127d..b99a7f2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx4/Makefile
@@ -6,5 +6,5 @@ mlx4_core-y :=	alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
 obj-$(CONFIG_MLX4_EN)               += mlx4_en.o
 
 mlx4_en-y := 	en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
-		en_resources.o en_netdev.o en_selftest.o
+		en_resources.o en_netdev.o en_selftest.o en_timestamp.o
 mlx4_en-$(CONFIG_MLX4_EN_DCB) += en_dcb_nl.o
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index 7e64033..a681bf5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -240,9 +240,10 @@ static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 		__mlx4_cq_free_icm(dev, cqn);
 }
 
-int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
-		  struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
-		  unsigned vector, int collapsed)
+int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
+		  struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec,
+		  struct mlx4_cq *cq, unsigned vector, int collapsed,
+		  int timestamp_en)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cq_table *cq_table = &priv->cq_table;
@@ -276,6 +277,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
 	memset(cq_context, 0, sizeof *cq_context);
 
 	cq_context->flags	    = cpu_to_be32(!!collapsed << 18);
+	if (timestamp_en)
+		cq_context->flags  |= cpu_to_be32(1 << 19);
+
 	cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
 	cq_context->comp_eqn	    = priv->eq_table.eq[vector].eqn;
 	cq_context->log_page_size   = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index aa9c2f6..59d8318 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -77,6 +77,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err = 0;
 	char name[25];
+	int timestamp_en = 0;
 	struct cpu_rmap *rmap =
 #ifdef CONFIG_RFS_ACCEL
 		priv->dev->rx_cpu_rmap;
@@ -123,8 +124,13 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
 	if (!cq->is_tx)
 		cq->size = priv->rx_ring[cq->ring].actual_size;
 
-	err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
-			    cq->wqres.db.dma, &cq->mcq, cq->vector, 0);
+	if ((cq->is_tx && priv->hwtstamp_config.tx_type) ||
+	    (!cq->is_tx && priv->hwtstamp_config.rx_filter))
+		timestamp_en = 1;
+
+	err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
+			    &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq,
+			    cq->vector, 0, timestamp_en);
 	if (err)
 		return err;
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a52922e..b49c7b0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -280,6 +280,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
 		if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i]))
 			mdev->pndev[i] = NULL;
 	}
+
+	/* Initialize time stamp mechanism */
+	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
+		mlx4_en_init_timestamp(mdev);
+
 	return mdev;
 
 err_mr:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index edd9cb8..ac78127 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1517,6 +1517,75 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
+static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	/* device doesn't support time stamping */
+	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS))
+		return -EINVAL;
+
+	/* TX HW timestamp */
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+	case HWTSTAMP_TX_ON:
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	/* RX HW timestamp */
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (mlx4_en_timestamp_config(dev, config.tx_type, config.rx_filter)) {
+		config.tx_type = HWTSTAMP_TX_OFF;
+		config.rx_filter = HWTSTAMP_FILTER_NONE;
+	}
+
+	return copy_to_user(ifr->ifr_data, &config,
+			    sizeof(config)) ? -EFAULT : 0;
+}
+
+static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return mlx4_en_hwtstamp_ioctl(dev, ifr);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int mlx4_en_set_features(struct net_device *netdev,
 		netdev_features_t features)
 {
@@ -1542,6 +1611,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
 	.ndo_set_mac_address	= mlx4_en_set_mac,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= mlx4_en_change_mtu,
+	.ndo_do_ioctl		= mlx4_en_ioctl,
 	.ndo_tx_timeout		= mlx4_en_tx_timeout,
 	.ndo_vlan_rx_add_vid	= mlx4_en_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= mlx4_en_vlan_rx_kill_vid,
@@ -1629,6 +1699,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	if (err)
 		goto out;
 
+	/* Initialize time stamping config */
+	priv->hwtstamp_config.flags = 0;
+	priv->hwtstamp_config.tx_type = HWTSTAMP_TX_OFF;
+	priv->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+
 	/* Allocate page for receive rings */
 	err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
 				MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index 10c24c7..bfc9be8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -42,6 +42,7 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 			     int user_prio, struct mlx4_qp_context *context)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
+	struct net_device *dev = priv->dev;
 
 	memset(context, 0, sizeof *context);
 	context->flags = cpu_to_be32(7 << 16 | rss << MLX4_RSS_QPC_FLAG_OFFSET);
@@ -65,6 +66,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 	context->cqn_send = cpu_to_be32(cqn);
 	context->cqn_recv = cpu_to_be32(cqn);
 	context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
+	if (!(dev->features & NETIF_F_HW_VLAN_RX))
+		context->param3 |= cpu_to_be32(1 << 30);
 }
 
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 5aba5ec..2d8827c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -319,6 +319,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
 	}
 	ring->buf = ring->wqres.buf.direct.buf;
 
+	ring->hwtstamp_rx_filter = priv->hwtstamp_config.rx_filter;
+
 	return 0;
 
 err_hwq:
@@ -553,6 +555,7 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
 int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_cqe *cqe;
 	struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
 	struct mlx4_en_rx_alloc *frags;
@@ -566,6 +569,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 	struct ethhdr *ethh;
 	dma_addr_t dma;
 	u64 s_mac;
+	u64 timestamp;
 
 	if (!priv->port_up)
 		return 0;
@@ -651,8 +655,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 					gro_skb->data_len = length;
 					gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-					if (cqe->vlan_my_qpn &
-					    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) {
+					if ((cqe->vlan_my_qpn &
+					    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
+					    (dev->features & NETIF_F_HW_VLAN_RX)) {
 						u16 vid = be16_to_cpu(cqe->sl_vid);
 
 						__vlan_hwaccel_put_tag(gro_skb, vid);
@@ -662,8 +667,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 						gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
 
 					skb_record_rx_queue(gro_skb, cq->ring);
-					napi_gro_frags(&cq->napi);
 
+					if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
+						timestamp = mlx4_en_get_cqe_ts(cqe);
+						mlx4_en_fill_hwtstamps(mdev, skb_hwtstamps(gro_skb),
+								       timestamp);
+					}
+
+					napi_gro_frags(&cq->napi);
 					goto next;
 				}
 
@@ -696,10 +707,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 		if (dev->features & NETIF_F_RXHASH)
 			skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
 
-		if (be32_to_cpu(cqe->vlan_my_qpn) &
-		    MLX4_CQE_VLAN_PRESENT_MASK)
+		if ((be32_to_cpu(cqe->vlan_my_qpn) &
+			MLX4_CQE_VLAN_PRESENT_MASK) &&
+			(dev->features & NETIF_F_HW_VLAN_RX))
 			__vlan_hwaccel_put_tag(skb, be16_to_cpu(cqe->sl_vid));
 
+		if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
+			timestamp = mlx4_en_get_cqe_ts(cqe);
+			mlx4_en_fill_hwtstamps(mdev, skb_hwtstamps(skb),
+					       timestamp);
+		}
+
 		/* Push it up the stack */
 		netif_receive_skb(skb);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_timestamp.c b/drivers/net/ethernet/mellanox/mlx4/en_timestamp.c
new file mode 100644
index 0000000..783d493
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx4/en_timestamp.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/mlx4/device.h>
+
+#include "mlx4_en.h"
+
+#define CORE_CLOCK_MASK 0xffffffffffffULL
+
+int mlx4_en_timestamp_config(struct net_device *dev, int tx_type, int rx_filter)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	int port_up = 0;
+	int err = 0;
+
+	mutex_lock(&mdev->state_lock);
+	if (priv->port_up) {
+		port_up = 1;
+		mlx4_en_stop_port(dev);
+	}
+
+	mlx4_en_free_resources(priv);
+
+	en_warn(priv, "Changing Time Stamp configuration\n");
+
+	priv->hwtstamp_config.tx_type = tx_type;
+	priv->hwtstamp_config.rx_filter = rx_filter;
+
+	if (rx_filter != HWTSTAMP_FILTER_NONE)
+		dev->features &= ~NETIF_F_HW_VLAN_RX;
+	else
+		dev->features |= NETIF_F_HW_VLAN_RX;
+
+	err = mlx4_en_alloc_resources(priv);
+	if (err) {
+		en_err(priv, "Failed reallocating port resources\n");
+		goto out;
+	}
+	if (port_up) {
+		err = mlx4_en_start_port(dev);
+		if (err)
+			en_err(priv, "Failed starting port\n");
+	}
+
+out:
+	mutex_unlock(&mdev->state_lock);
+	netdev_features_change(dev);
+	return err;
+}
+
+/* read raw cycle counter (to be used by time counter) */
+static cycle_t mlx4_en_read_clock(const struct cyclecounter *tc)
+{
+	struct mlx4_en_dev *mdev =
+		container_of(tc, struct mlx4_en_dev, cycles);
+	struct mlx4_dev *dev = mdev->dev;
+
+	return mlx4_read_clock(dev) & CORE_CLOCK_MASK;
+}
+
+u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe)
+{
+	u64 ts;
+	struct mlx4_ts_cqe *ts_cqe = (struct mlx4_ts_cqe *)cqe;
+
+	ts = (u64) be32_to_cpu(ts_cqe->timestamp_hi) << 16
+		| (u64) be16_to_cpu(ts_cqe->timestamp_lo);
+
+	return ts;
+}
+
+void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
+			    struct skb_shared_hwtstamps *hwts,
+			    u64 timestamp)
+{
+	u64 nsec;
+
+	nsec = timecounter_cyc2time(&mdev->clock, timestamp);
+
+	memset(hwts, 0, sizeof(struct skb_shared_hwtstamps));
+	hwts->hwtstamp = ns_to_ktime(nsec);
+}
+
+void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
+{
+	struct mlx4_dev *dev = mdev->dev;
+	u64 temp_mult;
+
+	memset(&mdev->cycles, 0, sizeof(mdev->cycles));
+	mdev->cycles.read = mlx4_en_read_clock;
+	mdev->cycles.mask = CLOCKSOURCE_MASK(48);
+
+	/* we have hca_core_clock in MHz, so to translate cycles to nsecs
+	 * we need to divide cycles by freq and multiply by 1000;
+	 * in order to get precise result we shift left the value,
+	 * since we don't have floating point there;
+	 * at the end shift result back
+	 */
+	temp_mult = ((1ull * 1000) << 29) / dev->caps.hca_core_clock;
+	mdev->cycles.mult = (u32)temp_mult;
+	mdev->cycles.shift = 29;
+
+	timecounter_init(&mdev->clock, &mdev->cycles,
+			 ktime_to_ns(ktime_get_real()));
+}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index c10e3a6..61d0997 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -118,6 +118,8 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
 	} else
 		ring->bf_enabled = true;
 
+	ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
+
 	return 0;
 
 err_map:
@@ -193,8 +195,9 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
 
 static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 				struct mlx4_en_tx_ring *ring,
-				int index, u8 owner)
+				int index, u8 owner, u64 timestamp)
 {
+	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
 	struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
 	struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset;
@@ -205,6 +208,12 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 	int i;
 	__be32 *ptr = (__be32 *)tx_desc;
 	__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
+	struct skb_shared_hwtstamps hwts;
+
+	if (timestamp) {
+		mlx4_en_fill_hwtstamps(mdev, &hwts, timestamp);
+		skb_tstamp_tx(skb, &hwts);
+	}
 
 	/* Optimize the common case when there are no wraparounds */
 	if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
@@ -290,7 +299,7 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
 	while (ring->cons != ring->prod) {
 		ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring,
 						ring->cons & ring->size_mask,
-						!!(ring->cons & ring->size));
+						!!(ring->cons & ring->size), 0);
 		ring->cons += ring->last_nr_txbb;
 		cnt++;
 	}
@@ -316,6 +325,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 	struct mlx4_cqe *buf = cq->buf;
 	u32 packets = 0;
 	u32 bytes = 0;
+	u64 timestamp = 0;
+	struct mlx4_en_tx_info *tx_info;
 
 	if (!priv->port_up)
 		return;
@@ -323,6 +334,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 	index = cons_index & size_mask;
 	cqe = &buf[index];
 	ring_index = ring->cons & size_mask;
+	tx_info = &ring->tx_info[ring_index];
 
 	/* Process all completed CQEs */
 	while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
@@ -336,6 +348,9 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 		/* Skip over last polled CQE */
 		new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
 
+		if (tx_info->ts_requested)
+			timestamp = mlx4_en_get_cqe_ts(cqe);
+
 		do {
 			txbbs_skipped += ring->last_nr_txbb;
 			ring_index = (ring_index + ring->last_nr_txbb) & size_mask;
@@ -343,7 +358,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 			ring->last_nr_txbb = mlx4_en_free_tx_desc(
 					priv, ring, ring_index,
 					!!((ring->cons + txbbs_skipped) &
-							ring->size));
+					ring->size), timestamp);
 			packets++;
 			bytes += ring->tx_info[ring_index].nr_bytes;
 		} while (ring_index != new_index);
@@ -617,6 +632,16 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx_info->skb = skb;
 	tx_info->nr_txbb = nr_txbb;
 
+	/*
+	 * For timestamping add flag to skb_shinfo and
+	 * set flag for further reference
+	 */
+	if (ring->hwtstamp_tx_type == HWTSTAMP_TX_ON &&
+	    skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		tx_info->ts_requested = 1;
+	}
+
 	/* Prepare ctrl segement apart opcode+ownership, which depends on
 	 * whether LSO is used */
 	tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 29e0199..2e77913 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1195,6 +1195,28 @@ static void unmap_bf_area(struct mlx4_dev *dev)
 		io_mapping_free(mlx4_priv(dev)->bf_mapping);
 }
 
+cycle_t mlx4_read_clock(struct mlx4_dev *dev)
+{
+	u32 clockhi, clocklo, clockhi1;
+	cycle_t cycles;
+	int i;
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	for (i = 0; i < 10; i++) {
+		clockhi = swab32(readl(priv->clock_mapping));
+		clocklo = swab32(readl(priv->clock_mapping + 4));
+		clockhi1 = swab32(readl(priv->clock_mapping));
+		if (clockhi == clockhi1)
+			break;
+	}
+
+	cycles = (u64) clockhi << 32 | (u64) clocklo;
+
+	return cycles;
+}
+EXPORT_SYMBOL_GPL(mlx4_read_clock);
+
+
 static int map_internal_clock(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 9d27e42..63da290 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -40,6 +40,7 @@
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
 #ifdef CONFIG_MLX4_EN_DCB
 #include <linux/dcbnl.h>
 #endif
@@ -207,6 +208,7 @@ struct mlx4_en_tx_info {
 	u8 linear;
 	u8 data_offset;
 	u8 inl;
+	u8 ts_requested;
 };
 
 
@@ -262,6 +264,7 @@ struct mlx4_en_tx_ring {
 	struct mlx4_bf bf;
 	bool bf_enabled;
 	struct netdev_queue *tx_queue;
+	int hwtstamp_tx_type;
 };
 
 struct mlx4_en_rx_desc {
@@ -288,6 +291,7 @@ struct mlx4_en_rx_ring {
 	unsigned long packets;
 	unsigned long csum_ok;
 	unsigned long csum_none;
+	int hwtstamp_rx_filter;
 };
 
 
@@ -363,6 +367,8 @@ struct mlx4_en_dev {
 	u32                     priv_pdn;
 	spinlock_t              uar_lock;
 	u8			mac_removed[MLX4_MAX_PORTS + 1];
+	struct cyclecounter	cycles;
+	struct timecounter	clock;
 };
 
 
@@ -522,6 +528,7 @@ struct mlx4_en_priv {
 	bool wol;
 	struct device *ddev;
 	int base_tx_qpn;
+	struct hwtstamp_config hwtstamp_config;
 
 #ifdef CONFIG_MLX4_EN_DCB
 	struct ieee_ets ets;
@@ -622,6 +629,16 @@ void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
 void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
 u64 mlx4_en_mac_to_u64(u8 *addr);
 
+/* Functions for time stamping */
+u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe);
+void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
+			    struct skb_shared_hwtstamps *hwts,
+			    u64 timestamp);
+void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev);
+int mlx4_en_timestamp_config(struct net_device *dev,
+			     int tx_type,
+			     int rx_filter);
+
 /*
  * Globals
  */
diff --git a/include/linux/mlx4/cq.h b/include/linux/mlx4/cq.h
index 6f65b2c..98fa492 100644
--- a/include/linux/mlx4/cq.h
+++ b/include/linux/mlx4/cq.h
@@ -64,6 +64,22 @@ struct mlx4_err_cqe {
 	u8			owner_sr_opcode;
 };
 
+struct mlx4_ts_cqe {
+	__be32			vlan_my_qpn;
+	__be32			immed_rss_invalid;
+	__be32			g_mlpath_rqpn;
+	__be32			timestamp_hi;
+	__be16			status;
+	u8			ipv6_ext_mask;
+	u8			badfcs_enc;
+	__be32			byte_cnt;
+	__be16			wqe_index;
+	__be16			checksum;
+	u8			reserved;
+	__be16			timestamp_lo;
+	u8			owner_sr_opcode;
+} __packed;
+
 enum {
 	MLX4_CQE_VLAN_PRESENT_MASK	= 1 << 29,
 	MLX4_CQE_QPN_MASK		= 0xffffff,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 26ad190..b3ff5b6 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -40,6 +40,8 @@
 
 #include <linux/atomic.h>
 
+#include <linux/clocksource.h>
+
 #define MAX_MSIX_P_PORT		17
 #define MAX_MSIX		64
 #define MSIX_LEGACY_SZ		4
@@ -798,7 +800,7 @@ void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres,
 
 int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
 		  struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
-		  unsigned vector, int collapsed);
+		  unsigned vector, int collapsed, int timestamp_en);
 void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
 
 int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base);
@@ -990,4 +992,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, u8 port, int
 void mlx4_put_slave_node_guid(struct mlx4_dev *dev, int slave, __be64 guid);
 __be64 mlx4_get_slave_node_guid(struct mlx4_dev *dev, int slave);
 
+cycle_t mlx4_read_clock(struct mlx4_dev *dev);
+
 #endif /* MLX4_DEVICE_H */
-- 
1.7.1

^ permalink raw reply related

* [PATCH V1 1/3] net/mlx4_core: Add timestamping device capability
From: Or Gerlitz @ 2012-10-09 15:20 UTC (permalink / raw)
  To: davem; +Cc: netdev, Eugenia Emantayev, Or Gerlitz
In-Reply-To: <1349796013-31106-1-git-send-email-ogerlitz@mellanox.com>

From: Eugenia Emantayev <eugenia@mellanox.com>

Add new device capability for timestamping support and query FW to retrieve it.

Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com>
Reviewed-by: Yevgeny Petrilin <yevgenyp@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx4/fw.c |    7 ++++++-
 include/linux/mlx4/device.h             |    3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 4f30b99..01bc49b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -125,7 +125,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
 		[0] = "RSS support",
 		[1] = "RSS Toeplitz Hash Function support",
 		[2] = "RSS XOR Hash Function support",
-		[3] = "Device manage flow steering support"
+		[3] = "Device manage flow steering support",
+		[4] = "Time stamping support"
 	};
 	int i;
 
@@ -439,6 +440,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET		0x38
 #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
+#define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET	0x3e
 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
 #define QUERY_DEV_CAP_EXT_FLAGS_OFFSET		0x40
 #define QUERY_DEV_CAP_FLAGS_OFFSET		0x44
@@ -554,6 +556,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev_cap->fs_max_num_qp_per_entry = field;
 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
 	dev_cap->stat_rate_support = stat_rate;
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
+	if (field & 0x80)
+		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS;
 	MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
 	MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	dev_cap->flags = flags | (u64)ext_flags << 32;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 6d1acb0..dbdcc64 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -148,7 +148,8 @@ enum {
 	MLX4_DEV_CAP_FLAG2_RSS			= 1LL <<  0,
 	MLX4_DEV_CAP_FLAG2_RSS_TOP		= 1LL <<  1,
 	MLX4_DEV_CAP_FLAG2_RSS_XOR		= 1LL <<  2,
-	MLX4_DEV_CAP_FLAG2_FS_EN		= 1LL <<  3
+	MLX4_DEV_CAP_FLAG2_FS_EN		= 1LL <<  3,
+	MLX4_DEV_CAP_FLAG2_TS			= 1LL <<  4
 };
 
 #define MLX4_ATTR_EXTENDED_PORT_INFO	cpu_to_be16(0xff90)
-- 
1.7.1

^ permalink raw reply related

* [PATCH V1 2/3] net/mlx4_core: Read HCA frequency and map internal clock
From: Or Gerlitz @ 2012-10-09 15:20 UTC (permalink / raw)
  To: davem; +Cc: netdev, Eugenia Emantayev, Or Gerlitz
In-Reply-To: <1349796013-31106-1-git-send-email-ogerlitz@mellanox.com>

From: Eugenia Emantayev <eugenia@mellanox.com>

Read HCA frequency, read PCI clock bar and offset, map internal clock to PCI bar.

Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com>
Reviewed-by: Yevgeny Petrilin <yevgenyp@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx4/fw.c   |   11 +++++
 drivers/net/ethernet/mellanox/mlx4/fw.h   |    1 +
 drivers/net/ethernet/mellanox/mlx4/main.c |   58 +++++++++++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/mlx4.h |    6 ++-
 include/linux/mlx4/device.h               |    1 +
 5 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 01bc49b..ddcbfd6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -987,6 +987,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
 #define QUERY_FW_COMM_BASE_OFFSET      0x40
 #define QUERY_FW_COMM_BAR_OFFSET       0x48
 
+#define QUERY_FW_CLOCK_OFFSET	       0x50
+#define QUERY_FW_CLOCK_BAR	       0x58
+
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
 		return PTR_ERR(mailbox);
@@ -1061,6 +1064,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
 		 fw->comm_bar, fw->comm_base);
 	mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
 
+	MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
+	MLX4_GET(fw->clock_bar,    outbox, QUERY_FW_CLOCK_BAR);
+	fw->clock_bar = (fw->clock_bar >> 6) * 2;
+	mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
+		 fw->clock_bar, fw->clock_offset);
+
 	/*
 	 * Round up number of system pages needed in case
 	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
@@ -1326,6 +1335,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 	int err;
 
 #define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
+#define QUERY_HCA_CORE_CLOCK_OFFSET	0x0c
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -1340,6 +1350,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 		goto out;
 
 	MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
+	MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
 
 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 85abe9c..9b8775c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -162,6 +162,7 @@ struct mlx4_init_hca_param {
 	u64 global_caps;
 	u16 log_mc_entry_sz;
 	u16 log_mc_hash_sz;
+	u16 hca_core_clock;
 	u8  log_num_qps;
 	u8  log_num_srqs;
 	u8  log_num_cqs;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 80df2ab..29e0199 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -497,6 +497,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
 
 	mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
 
+	dev->caps.hca_core_clock = hca_param.hca_core_clock;
+
 	memset(&dev_cap, 0, sizeof(dev_cap));
 	dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp;
 	err = mlx4_dev_cap(dev, &dev_cap);
@@ -1193,8 +1195,31 @@ static void unmap_bf_area(struct mlx4_dev *dev)
 		io_mapping_free(mlx4_priv(dev)->bf_mapping);
 }
 
+static int map_internal_clock(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	priv->clock_mapping = ioremap(pci_resource_start(dev->pdev,
+				priv->fw.clock_bar) +
+				priv->fw.clock_offset, MLX4_CLOCK_SIZE);
+
+	if (!priv->clock_mapping)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void unmap_internal_clock(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	if (priv->clock_mapping)
+		iounmap(priv->clock_mapping);
+}
+
 static void mlx4_close_hca(struct mlx4_dev *dev)
 {
+	unmap_internal_clock(dev);
 	unmap_bf_area(dev);
 	if (mlx4_is_slave(dev))
 		mlx4_slave_exit(dev);
@@ -1369,6 +1394,38 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 			mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
 			goto err_free_icm;
 		}
+		/*
+		 * If TS is supported by FW
+		 * read HCA frequency by QUERY_HCA command
+		 */
+		if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
+			memset(&init_hca, 0, sizeof(init_hca));
+			err = mlx4_QUERY_HCA(dev, &init_hca);
+			if (err) {
+				mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n");
+				dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+			} else {
+				dev->caps.hca_core_clock =
+					init_hca.hca_core_clock;
+			}
+
+			/* In case we got HCA frequency 0 - disable timestamping
+			 * to avoid dividing by zero
+			 */
+			if (!dev->caps.hca_core_clock) {
+				dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+				mlx4_err(dev, "HCA frequency is 0. " \
+					 "Timestamping is not supported.");
+			} else if (map_internal_clock(dev)) {
+				/*
+				 * Map internal clock,
+				 * in case of failure disable timestamping
+				 */
+				dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+				mlx4_err(dev, "Failed to map internal clock. " \
+					 "Timestamping is not supported.\n");
+			}
+		}
 	} else {
 		err = mlx4_init_slave(dev);
 		if (err) {
@@ -1402,6 +1459,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 	return 0;
 
 unmap_bf:
+	unmap_internal_clock(dev);
 	unmap_bf_area(dev);
 
 err_close:
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 1cf4203..ddf3246 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -90,7 +90,8 @@ enum {
 	MLX4_HCR_SIZE		= 0x0001c,
 	MLX4_CLR_INT_SIZE	= 0x00008,
 	MLX4_SLAVE_COMM_BASE	= 0x0,
-	MLX4_COMM_PAGESIZE	= 0x1000
+	MLX4_COMM_PAGESIZE	= 0x1000,
+	MLX4_CLOCK_SIZE		= 0x00008
 };
 
 enum {
@@ -388,6 +389,7 @@ struct mlx4_fw {
 	u64			clr_int_base;
 	u64			catas_offset;
 	u64			comm_base;
+	u64			clock_offset;
 	struct mlx4_icm	       *fw_icm;
 	struct mlx4_icm	       *aux_icm;
 	u32			catas_size;
@@ -395,6 +397,7 @@ struct mlx4_fw {
 	u8			clr_int_bar;
 	u8			catas_bar;
 	u8			comm_bar;
+	u8			clock_bar;
 };
 
 struct mlx4_comm {
@@ -814,6 +817,7 @@ struct mlx4_priv {
 	struct list_head	bf_list;
 	struct mutex		bf_mutex;
 	struct io_mapping	*bf_mapping;
+	void __iomem            *clock_mapping;
 	int			reserved_mtts;
 	int			fs_hash_mode;
 	u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index dbdcc64..26ad190 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -420,6 +420,7 @@ struct mlx4_caps {
 	u32			max_counters;
 	u8			port_ib_mtu[MLX4_MAX_PORTS + 1];
 	u16			sqp_demux;
+	u16			hca_core_clock;
 };
 
 struct mlx4_buf_list {
-- 
1.7.1

^ permalink raw reply related

* Re: compound skb frag pages appearing in start_xmit
From: Eric Dumazet @ 2012-10-09 14:51 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Eric Dumazet, xen-devel, netdev@vger.kernel.org,
	Konrad Rzeszutek Wilk, Sander Eikelenboom
In-Reply-To: <1349793630.21847.208.camel@zakaz.uk.xensource.com>

On Tue, 2012-10-09 at 15:40 +0100, Ian Campbell wrote:
> On Tue, 2012-10-09 at 15:27 +0100, Eric Dumazet wrote:
> > On Tue, 2012-10-09 at 15:17 +0100, Ian Campbell wrote:
> > 
> > > Does the higher order pages effectively reduce the number of frags which
> > > are in use? e.g if MAX_SKB_FRAGS is 16, then for order-0 pages you could
> > > have 64K worth of frag data.
> > > 
> > > If we switch to order-3 pages everywhere then can the skb contain 512K
> > > of data, or does the effective maximum number of frags in an skb reduce
> > > to 2?
> > 
> > effective number of frags reduce to 2 or 3
> > 
> > (We still limit GSO packets to ~63536 bytes)
> 
> Great! Then I think the fix is more/less trivial...
> 
> As an aside, when the skb head is < 4096 bytes is that necessarily a
> compound page or might it just be a large kmalloc area?
> 

skb->head can be either allocated by kmalloc() (standard alloc_skb()) or
a page frag (if allocated in rx path)

Not sure its related to headlen/size...

^ permalink raw reply

* Using phylib with a MAC-handled interrupt
From: Thomas Petazzoni @ 2012-10-09 16:17 UTC (permalink / raw)
  To: afleming
  Cc: netdev, Florian Fainelli, Lior Amsalem, Gregory Clément,
	Maen Suleiman

Hello Andy,

I am currently working on a network driver for the MAC present in the
latest Marvell ARM SoCs. This MAC is capable of polling the PHY in
hardware, which avoids the need for Linux to poll the PHY regularly.

Therefore, I am currently trying to do an integration of the driver with
the phylib using the third solution you listed at
http://lists.openwall.net/netdev/2008/06/06/38.

Unfortunately, with the current Linux kernel, the phylib continues to
poll the PHY registers regularly even if phydev->irq is set to
PHY_IGNORE_INTERRUPT. This is due to the fact that the phylib code
override phydev->irq to be PHY_POLL whenever the PHY driver doesn't
support interrupt, which isn't correct. This is fixed by the below
patch.

However, even with the below patch, I cannot implement your solution
three described in http://lists.openwall.net/netdev/2008/06/06/38 :
taking a mutex in an interrupt handler is not possible. Therefore, I
cannot change the phydev->state field from my MAC driver to force the
PHY state machine to re-read the status of the PHY.

I tried to force the execution of the phydev->phy_queue workqueue, but
unfortunately, simply calling schedule_work(&phydev->phy_queue)
from my interrupt handler causes problems:

WARNING: at /home/thomas/projets/linux-2.6/kernel/workqueue.c:1033 __queue_work+0x1c0/0x1d8()

This is apparently because schedule_work() doesn't like when the
workqueue is already scheduled for execution, but I am not sure how to
properly handle this case.

What I would like to do is from my MAC interrupt handler, tell the
phylib "hey, something has changed, you should re-read the PHY
registers and if needed call my ->adjust_link() callback".

How can I do that with the phylib?

Thanks,

Thomas

From 3eae62a1adb08229ea4d20068ef868b731b020cb Mon Sep 17 00:00:00 2001
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Date: Tue, 9 Oct 2012 18:10:21 +0200
Subject: [PATCH] net: phy: fix support of PHY_IGNORE_INTERRUPT

When PHY_IGNORE_INTERRUPT is set as the phydev->irq, then the phylib
shouldn't poll the PHY regularly, but instead let the MAC driver tell
the phylib when to re-read the PHY status. Unfortunately, as soon as
the PHY didn't had PHY_HAS_INTERRUPT set, the phylib was forcing
PHY_POLL as the interrupt.

Also fix two other places that test against PHY_POLL while they should
instead be testing if we have an IRQ or not.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 drivers/net/phy/phy.c        |    4 ++--
 drivers/net/phy/phy_device.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7ca2ff9..a1d265f 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -709,7 +709,7 @@ void phy_stop(struct phy_device *phydev)
 	if (PHY_HALTED == phydev->state)
 		goto out_unlock;
 
-	if (phydev->irq != PHY_POLL) {
+	if (phydev->irq > 0) {
 		/* Disable PHY Interrupts */
 		phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
 
@@ -896,7 +896,7 @@ void phy_state_machine(struct work_struct *work)
 
 			phydev->adjust_link(phydev->attached_dev);
 
-			if (PHY_POLL != phydev->irq)
+			if (phydev->irq > 0)
 				err = phy_config_interrupt(phydev,
 						PHY_INTERRUPT_ENABLED);
 			break;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8af46e8..110b3a3 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1011,7 +1011,7 @@ static int phy_probe(struct device *dev)
 	phydev->drv = phydrv;
 
 	/* Disable the interrupt if the PHY doesn't support it */
-	if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+	if (!(phydrv->flags & PHY_HAS_INTERRUPT) && phydev->irq > 0)
 		phydev->irq = PHY_POLL;
 
 	mutex_lock(&phydev->lock);
-- 
1.7.9.5


-- 
Thomas Petazzoni                http://thomas.enix.org
MapOSMatic                      http://www.maposmatic.org
Logiciels Libres à Toulouse     http://www.toulibre.org
Embedded Linux                  http://www.free-electrons.com

^ permalink raw reply related

* Re: [PATCH] ipv6: gro: fix PV6_GRO_CB(skb)->proto problem
From: David Miller @ 2012-10-09 16:44 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, herbert
In-Reply-To: <1349787985.21172.4305.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 09 Oct 2012 15:06:25 +0200

> Hmm, it appears its a false alarm, you can remove it from stable
> candidates.

Done.

> I'll send a patch to remove this double copy in net-next

Ok.

^ permalink raw reply

* Re: setting flow spec rules under vswitch configuration
From: Ben Hutchings @ 2012-10-09 16:48 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: Rony Efraim, netdev, Amir Vadai
In-Reply-To: <5073F073.3060403@mellanox.com>

On Tue, 2012-10-09 at 11:37 +0200, Or Gerlitz wrote:
> Hi Ben,
> 
> Looking on kernel ethtool flow steering APIs in the context of a device
> which is used as the uplink of a virtual switch, the admin should be able
> to provide flow specification and action (e.g drop) that relates to traffic
> coming from a specific port of the switch e.g that relates to a certain 
> VM,etc.
> 
> For that end, we need to be able to specify both the L3/L4 attributes of
> the flow and an L2 spec, that is the L2 spec containing the destination MAC
> can't be assumed as the one of that device.
> 
> Specifically, in struct ethtool_rx_ntuple_flow_spec, I think we should 
> let the
> to provide an ethhdr even when L3/L4 spec is given, make sense?

Yes, but the ethertype looks redundant - the inner type is implied by
the L3 flow type and the outer type for a VLAN-encapsulated packet
should be matched against ethtool_flow_ext::vlan_etype.  Might be better
to avoid confusion by just specifying the L2 addresses.

> if yes, how
> would you like to see this change, add a union entry that contains both, 
> or in
> another way?

struct ethtool_rx_ntuple_flow_spec is obsolete; struct
ethtool_rx_flow_spec is what we have to consider.  That effectively has:

	union ethtool_flow_union {
		struct ethtool_tcpip4_spec		tcp_ip4_spec;
		struct ethtool_tcpip4_spec		udp_ip4_spec;
		struct ethtool_tcpip4_spec		sctp_ip4_spec;
		struct ethtool_ah_espip4_spec		ah_ip4_spec;
		struct ethtool_ah_espip4_spec		esp_ip4_spec;
		struct ethtool_usrip4_spec		usr_ip4_spec;
		struct ethhdr				ether_spec;
		/* above are up to 16 bytes long */
		__u8					hdata[60];
	} h_u;
	struct ethtool_flow_ext {
		__be16	vlan_etype;
		__be16	vlan_tci;
		__be32	data[2];
	} h_ext;
	union ethtool_flow_union m_u;
	struct ethtool_flow_ext m_ext;

So ethtool_flow_union::hdata currently provides 44 bytes of padding
between the per-protocol flow specs and ethtool_flow_ext, which can be
reallocated to the *beginning* of ethtool_flow_ext.  At some point we'll
presumably want to add IPv6 flow specs, which will use up 24 bytes of
that padding at the front.  So we can potentially extend
ethtool_flow_ext by up to 20 bytes.

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.

^ permalink raw reply

* Re: [net 0/3][pull request] Intel Wired LAN Driver Updates
From: David Miller @ 2012-10-09 16:51 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, sassmann
In-Reply-To: <1349777612-30149-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue,  9 Oct 2012 03:13:29 -0700

> This series contains updates to ixgbe, ixgbevf and e1000e.
> 
> The following are changes since commit 66eef59f22275002f621ff9d951886b513d011b3:
>   net: fix typo in freescale/ucc_geth.c
> and are available in the git repository at:
>   git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master
> 
> Alexander Duyck (1):
>   ixgbe/ixgbevf: Limit maximum jumbo frame size to 9.5K to avoid Tx
>     hangs
> 
> Bruce Allan (1):
>   e1000e: add device IDs for i218
> 
> Greg Rose (1):
>   ixgbevf: Set the netdev number of Tx queues

Pulled but please let's get that multi-month-old e1000e BQL bug fixed.

Thanks.

^ permalink raw reply

* Re: [PATCH V1 2/3] net/mlx4_core: Read HCA frequency and map internal clock
From: Joe Perches @ 2012-10-09 16:54 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: davem, netdev, Eugenia Emantayev
In-Reply-To: <1349796013-31106-3-git-send-email-ogerlitz@mellanox.com>

On Tue, 2012-10-09 at 17:20 +0200, Or Gerlitz wrote:
> Read HCA frequency, read PCI clock bar and offset, map internal clock to PCI bar.

trivial comments below:

> diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
[]
> @@ -1193,8 +1195,31 @@ static void unmap_bf_area(struct mlx4_dev *dev)
>  		io_mapping_free(mlx4_priv(dev)->bf_mapping);
>  }
>  
> +static int map_internal_clock(struct mlx4_dev *dev)
> +{
> +	struct mlx4_priv *priv = mlx4_priv(dev);
> +
> +	priv->clock_mapping = ioremap(pci_resource_start(dev->pdev,
> +				priv->fw.clock_bar) +
> +				priv->fw.clock_offset, MLX4_CLOCK_SIZE);

I think this is misleading indentation style.
Perhaps this'd be nicer as something like:

	priv->clock_mapping =
		ioremap(pci_resource_start(dev->pdev, priv->fw.clock_bar) +
			priv->fw.clock_offset, MLX4_CLOCK_SIZE);

[]

> +			/* In case we got HCA frequency 0 - disable timestamping
> +			 * to avoid dividing by zero
> +			 */
> +			if (!dev->caps.hca_core_clock) {
> +				dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
> +				mlx4_err(dev, "HCA frequency is 0. " \
> +					 "Timestamping is not supported.");

These are missing terminating newlines.
Please don't split format strings like this.  It's hard to grep.
Especially please don't use unnecessary line continuations.
The compiler will concatenate these strings without the \.

^ permalink raw reply

* Re: [PATCH 11/11] net: xilinx: Show csum in bootlog
From: Ben Hutchings @ 2012-10-09 16:56 UTC (permalink / raw)
  To: monstr
  Cc: netdev, linux-kernel, Anirudha Sarangi, John Linn, Grant Likely,
	Rob Herring, David S. Miller, John Linn
In-Reply-To: <5073E988.60701@monstr.eu>

On Tue, 2012-10-09 at 11:08 +0200, Michal Simek wrote:
> On 10/05/2012 03:51 PM, Ben Hutchings wrote:
> > On Fri, 2012-10-05 at 11:35 +0200, Michal Simek wrote:
> >> On 10/04/2012 09:15 PM, Ben Hutchings wrote:
> >>> On Thu, 2012-10-04 at 20:14 +0200, Michal Simek wrote:
> >>>> Just show current setting in bootlog.
> >>> [...]
> >>>> --- a/drivers/net/ethernet/xilinx/ll_temac_main.c
> >>>> +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
> >>>> @@ -1052,12 +1052,14 @@ static int __devinit temac_of_probe(struct platform_device *op)
> >>>>    	/* Setup checksum offload, but default to off if not specified */
> >>>>    	lp->temac_features = 0;
> >>>>    	p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
> >>>> +	dev_info(&op->dev, "TX_CSUM %d\n", be32_to_cpup(p));
> >>>>    	if (p && be32_to_cpu(*p)) {
> >>>>    		lp->temac_features |= TEMAC_FEATURE_TX_CSUM;
> >>>>    		/* Can checksum TCP/UDP over IPv4. */
> >>>>    		ndev->features |= NETIF_F_IP_CSUM;
> >>>>    	}
> >>>>    	p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
> >>>> +	dev_info(&op->dev, "RX_CSUM %d\n", be32_to_cpup(p));
> >>> [...]
> >>>
> >>> Is there any particular reason you think this needs to be logged by
> >>> default, rather than letting users run ethtool -k?  I suggest using
> >>> dev_dbg() instead.
> >>
> >> Ok. I have looked at it and there are missing some bits in ndev->features.
> >>
> >> Can you please check that my setting is correct?
> >>
> >> It is SG DMA ip/driver.
> >> ndev->features = NETIF_F_FRAGLIST | NETIF_F_SG
> >
> > NETIF_F_SG only; NETIF_F_FRAGLIST means you can handle skbs chained
> > through the frag_list pointer.
> 
> The driver is able to handle skb fragments too. temac_start_xmit

"git grep -w -E 'frag_list|skb_walk_frags|skb_to_sgvec' drivers/net/ethernet/xilinx"
returns nothing in net-next.

[...]
> >> rx Full csum -> NETIF_F_RXCSUM
> >>
> >> Is there any option to support partial csum?
> >
> > There is no need to differentiate these in the device features.  For TX
> > the stack needs to know whether to use a software fallback before
> > passing the skb to you, but on RX it looks at the ip_summed field of
> > each skb you pass up.
> 
> Hardware can be setup asymmetrically. It means enable CSUM only on RX or TX.
> All combination are valid.
> The point here is if Linux is not able to handle this then we have to
> create logic in the driver to support these options too.

Linux handles this just fine.  The point is you don't have to tell the
stack in advance whether or what kind of RX checksum validation your
devices will do.  (In fact the only reason that feature flag exists at
all is so that it can be generically exposed through the ethtool API.)

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.

^ permalink raw reply

* Re: [GIT PULL] Disintegrate UAPI for net
From: David Miller @ 2012-10-09 17:17 UTC (permalink / raw)
  To: dhowells; +Cc: netdev, linux-kernel
In-Reply-To: <30725.1349789433@warthog.procyon.org.uk>

From: David Howells <dhowells@redhat.com>
Date: Tue, 09 Oct 2012 14:30:33 +0100

> Can you merge the following branch into the net tree please.
> 
> This is to complete part of the Userspace API (UAPI) disintegration for which
> the preparatory patches were pulled recently.  After these patches, userspace
> headers will be segregated into:
> 
> 	include/uapi/linux/.../foo.h
> 
> for the userspace interface stuff, and:
> 
> 	include/linux/.../foo.h
> 
> for the strictly kernel internal stuff.
> 
> ---
> The following changes since commit 9e2d8656f5e8aa214e66b462680cf86b210b74a8:
> 
>   Merge branch 'akpm' (Andrew's patch-bomb) (2012-10-09 16:23:15 +0900)
> 
> are available in the git repository at:
> 
> 
>   git://git.infradead.org/users/dhowells/linux-headers.git tags/disintegrate-net-20121009

Ok I pulled this and the ISDN one too.

Thanks.

^ permalink raw reply

* Re: [PATCH net] e1000e: Change wthresh to 1 to avoid possible Tx stalls.
From: Jesse Brandeburg @ 2012-10-09 17:36 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Frank Reppin, netdev, Jeff Kirsher, jesse.brandeburg, e1000-devel
In-Reply-To: <1349762863.21172.3848.camel@edumazet-glaptop>

> > > Jesse did not share any performance numbers with me, I am sure he can
> > > give some background tomorrow when he is back online.
> > > 
> > > I am working on an alternative patch now and should have something to
> > > share tomorrow.
> > Please allow me to ask if there's any progess here?
> > 
> > I've tried 3.5.4 a couple of days ago on a SuperMicro X8SIE-LN4 (82574L)
> > and could still observe severe latency (up to 3000ms) spikes.
> > 
> > Applying Hiroakis suggested patch did fix this for me as well.
> > [please note as well that I didn't had this issue in any 3.4.x kernel
> > before - so +1 for fixing the regression]

I'm not sure what went wrong internally here that this hasn't been
fixed, and I'm personally embarrassed.  I am working on it until I have
a patch/solution.

currently am trying to reproduce the issue, am in some weird how to
use BQL limbo, the lack of documentation on user usage of BQL is slowing
me down.

Hints or clues (I'm trying to follow the repro steps mentioned in
some related threads) are appreciated.

^ permalink raw reply

* Re: [PATCH] pch_gbe: Fix build error by selecting all the possible dependencies.
From: David Miller @ 2012-10-09 17:51 UTC (permalink / raw)
  To: haicheng.lee; +Cc: haicheng.li, linux-kernel, netdev, fengguang.wu
In-Reply-To: <1349775792-12573-1-git-send-email-haicheng.lee@gmail.com>

From: Haicheng Li <haicheng.lee@gmail.com>
Date: Tue,  9 Oct 2012 17:43:12 +0800

> Fengguang reported a kernel build failure as following:
> drivers/built-in.o: In function `pch_gbe_ioctl':
> pch_gbe_main.c:(.text+0x510370): undefined reference to `pch_ch_control_write'
> pch_gbe_main.c:(.text+0x510393): undefined reference to `pch_ch_control_write'
> pch_gbe_main.c:(.text+0x5103b3): undefined reference to `pch_ch_control_write'
> ...
> 
> It's a regression by commit da1586461. The root cause is that
> the CONFIG_PPS is not set there, consequently CONFIG_PTP_1588_CLOCK
> can not be set anyway, which finally causes ptp_pch and pch_gbe_main
> build failures.
> 
> As David prefers to use *select* to fix such module co-dependency issues,
> this patch explicitly selects all the possible dependencies of PCH_PTP.
> 
> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> Reviewed-by: David S. Miller <davem@davemloft.net>
> Signed-off-by: Haicheng Li <haicheng.lee@gmail.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 2/5] pktgen: set different default min_pkt_size for different protocols
From: David Miller @ 2012-10-09 17:55 UTC (permalink / raw)
  To: amwang; +Cc: netdev
In-Reply-To: <1349777131-4425-2-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>
Date: Tue,  9 Oct 2012 18:05:28 +0800

> ETH_ZLEN is too small for IPv6, so this default value is not
> suitable.
> 
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <amwang@redhat.com>

pkt_dev->max_pkt_size is no longer being initialized.

At least set it to whatever you compute in pkt_dev->min_pkt_size

^ permalink raw reply

* Re: [PATCH] netdev/phy: Prototype of_mdio_find_bus()
From: David Miller @ 2012-10-09 17:55 UTC (permalink / raw)
  To: broonie; +Cc: david.daney, netdev
In-Reply-To: <1349772944-14289-1-git-send-email-broonie@opensource.wolfsonmicro.com>

From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue,  9 Oct 2012 17:55:43 +0900

> Ensure that of_mdio_find_bus() matches the prototype in the header (and
> stop sparse complaining) by including the header with the prototype.
> 
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Applied.

^ permalink raw reply

* Re: [patch] farsync: fix support for over 30 cards
From: David Miller @ 2012-10-09 17:55 UTC (permalink / raw)
  To: dan.carpenter; +Cc: kevin.curtis, netdev, kernel-janitors
In-Reply-To: <20121009072047.GB19159@elgon.mountain>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 9 Oct 2012 10:20:48 +0300

> We're trying to fill a 64 bit bitmap but only the lower 30 shifts work
> because the shift wraps around.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply

* Re: [PATCH] be2net: Remove code that stops further access to BE NIC based on UE bits
From: David Miller @ 2012-10-09 17:55 UTC (permalink / raw)
  To: ajit.khaparde; +Cc: netdev
In-Reply-To: <20121009041821.GA16595@akhaparde-VBox>

From: Ajit Khaparde <ajit.khaparde@emulex.com>
Date: Mon, 8 Oct 2012 23:18:21 -0500

> On certain platforms, BE hardware could  falsely indicate UE.
> For BE family of NICs, do not set hw_error based on the UE bits.
> If there was a real fatal error, the corresponding h/w block will
> automatically go offline and stop traffic.
> 
> Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>

Applied.

^ permalink raw reply

* Re: [PATCH v2] RDS: fix rds-ping spinlock recursion
From: David Miller @ 2012-10-09 17:58 UTC (permalink / raw)
  To: jeff.liu
  Cc: rds-devel, venkat.x.venkatsubra, dan.carpenter, james.l.morris,
	netdev
In-Reply-To: <5073AEB7.9060309@oracle.com>

From: Jeff Liu <jeff.liu@oracle.com>
Date: Tue, 09 Oct 2012 12:57:27 +0800

> This is the revised patch for fixing rds-ping spinlock recursion according to Venkat's suggestions.
> 
> RDS ping/pong over TCP feature has been broken for years(2.6.39 to 3.6.0) since we
> have to set TCP cork and call kernel_sendmsg() between ping/pong which both need to
> lock "struct sock *sk". However, this lock has already been hold before rds_tcp_data_ready()
> callback is triggerred. As a result, we always facing spinlock resursion which would resulting
> in system panic.
> 
> Given that RDS ping is only used to test the connectivity and not for serious performance measurements,
> we can queue the pong transmit to rds_wq as a delayed response.
> 
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> CC: Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
> CC: David S. Miller <davem@davemloft.net>
> CC: James Morris <james.l.morris@oracle.com>
> Signed-off-by: Jie Liu <jeff.liu@oracle.com>

Applied and queued up for -stable, thanks.

^ permalink raw reply

* [PATCH 0/6] VXLAN fixes
From: Stephen Hemminger @ 2012-10-09 17:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

These fix some bugs found in followup testing with VXLAN.

^ permalink raw reply

* [PATCH 2/6] vxlan: use ip_route_output
From: Stephen Hemminger @ 2012-10-09 17:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20121009175637.048993312@vyatta.com>

[-- Attachment #1: vxlan-route-output.patch --]
[-- Type: text/plain, Size: 1057 bytes --]

Select source address for VXLAN packet based on route destination
and don't lie to route code: VXLAN is not GRE.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/drivers/net/vxlan.c	2012-10-09 10:48:56.546879617 -0700
+++ b/drivers/net/vxlan.c	2012-10-09 10:49:01.334832146 -0700
@@ -676,9 +676,11 @@ static netdev_tx_t vxlan_xmit(struct sk_
 
 	hash = skb_get_rxhash(skb);
 
-	rt = ip_route_output_gre(dev_net(dev), &fl4, dst,
-				 vxlan->saddr, vxlan->vni,
-				 RT_TOS(tos), vxlan->link);
+	fl4.flowi4_oif = vxlan->link;
+	fl4.flowi4_tos = RT_TOS(tos);
+	fl4.daddr = dst;
+	fl4.saddr = vxlan->saddr;
+	rt = ip_route_output_key(dev_net(dev), &fl4);
 	if (IS_ERR(rt)) {
 		netdev_dbg(dev, "no route to %pI4\n", &dst);
 		dev->stats.tx_carrier_errors++;
@@ -720,7 +722,7 @@ static netdev_tx_t vxlan_xmit(struct sk_
 	iph->frag_off	= df;
 	iph->protocol	= IPPROTO_UDP;
 	iph->tos	= vxlan_ecn_encap(tos, old_iph, skb);
-	iph->daddr	= fl4.daddr;
+	iph->daddr	= dst;
 	iph->saddr	= fl4.saddr;
 	iph->ttl	= ttl ? : ip4_dst_hoplimit(&rt->dst);
 

^ permalink raw reply

* [PATCH 4/6] VXLAN bases source UDP port based on flow to help the receiver to be able to load balance based on outer header flow.
From: Stephen Hemminger @ 2012-10-09 17:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20121009175637.048993312@vyatta.com>

[-- Attachment #1: vxlan-port-range.patch --]
[-- Type: text/plain, Size: 5757 bytes --]

This patch restricts the port range to the normal UDP local
ports, and allows overriding via configruation.

It also uses jhash of Ethernet header when looking at flows
with out know L3 header.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
 drivers/net/vxlan.c     |   62 ++++++++++++++++++++++++++++++++++++++++++++----
 include/linux/if_link.h |    6 ++++
 2 files changed, 63 insertions(+), 5 deletions(-)

--- a/drivers/net/vxlan.c	2012-10-09 10:49:05.318792637 -0700
+++ b/drivers/net/vxlan.c	2012-10-09 10:49:08.238763697 -0700
@@ -106,6 +106,8 @@ struct vxlan_dev {
 	__be32	          gaddr;	/* multicast group */
 	__be32		  saddr;	/* source address */
 	unsigned int      link;		/* link to multicast over */
+	__u16		  port_min;	/* source port range */
+	__u16		  port_max;
 	__u8		  tos;		/* TOS override */
 	__u8		  ttl;
 	bool		  learn;
@@ -650,12 +652,29 @@ static void vxlan_set_owner(struct net_d
 	skb->destructor = vxlan_sock_free;
 }
 
+/* Compute source port for outgoing packet
+ *   first choice to use L4 flow hash since it will spread
+ *     better and maybe available from hardware
+ *   secondary choice is to use jhash on the Ethernet header
+ */
+static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+	unsigned int range = (vxlan->port_max - vxlan->port_min) + 1;
+	u32 hash;
+
+	hash = skb_get_rxhash(skb);
+	if (!hash)
+		hash = jhash(skb->data, 2 * ETH_ALEN,
+			     (__force u32) skb->protocol);
+
+	return (((u64) hash * range) >> 32) + vxlan->port_min;
+}
+
 /* Transmit local packets over Vxlan
  *
  * Outer IP header inherits ECN and DF from inner header.
  * Outer UDP destination is the VXLAN assigned port.
- *           source port is based on hash of flow if available
- *                       otherwise use a random value
+ *           source port is based on hash of flow
  */
 static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -667,8 +686,8 @@ static netdev_tx_t vxlan_xmit(struct sk_
 	struct udphdr *uh;
 	struct flowi4 fl4;
 	unsigned int pkt_len = skb->len;
-	u32 hash;
 	__be32 dst;
+	__u16 src_port;
 	__be16 df = 0;
 	__u8 tos, ttl;
 	int err;
@@ -691,7 +710,7 @@ static netdev_tx_t vxlan_xmit(struct sk_
 	if (tos == 1)
 		tos = vxlan_get_dsfield(old_iph, skb);
 
-	hash = skb_get_rxhash(skb);
+	src_port = vxlan_src_port(vxlan, skb);
 
 	fl4.flowi4_oif = vxlan->link;
 	fl4.flowi4_tos = RT_TOS(tos);
@@ -726,7 +745,7 @@ static netdev_tx_t vxlan_xmit(struct sk_
 	uh = udp_hdr(skb);
 
 	uh->dest = htons(vxlan_port);
-	uh->source = hash ? :random32();
+	uh->source = htons(src_port);
 
 	uh->len = htons(skb->len);
 	uh->check = 0;
@@ -954,6 +973,7 @@ static void vxlan_setup(struct net_devic
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	unsigned h;
+	int low, high;
 
 	eth_hw_addr_random(dev);
 	ether_setup(dev);
@@ -973,6 +993,10 @@ static void vxlan_setup(struct net_devic
 	vxlan->age_timer.function = vxlan_cleanup;
 	vxlan->age_timer.data = (unsigned long) vxlan;
 
+	inet_get_local_port_range(&low, &high);
+	vxlan->port_min = low;
+	vxlan->port_max = high;
+
 	vxlan->dev = dev;
 
 	for (h = 0; h < FDB_HASH_SIZE; ++h)
@@ -989,6 +1013,7 @@ static const struct nla_policy vxlan_pol
 	[IFLA_VXLAN_LEARNING]	= { .type = NLA_U8 },
 	[IFLA_VXLAN_AGEING]	= { .type = NLA_U32 },
 	[IFLA_VXLAN_LIMIT]	= { .type = NLA_U32 },
+	[IFLA_VXLAN_PORT_RANGE] = { .len  = sizeof(struct ifla_vxlan_port_range) },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1021,6 +1046,18 @@ static int vxlan_validate(struct nlattr
 			return -EADDRNOTAVAIL;
 		}
 	}
+
+	if (data[IFLA_VXLAN_PORT_RANGE]) {
+		const struct ifla_vxlan_port_range *p
+			= nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+
+		if ((int)(ntohs(p->high) - ntohs(p->low)) < 1) {
+			pr_debug("port range %u .. %u not valid\n",
+				 ntohs(p->low), ntohs(p->high));
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -1071,6 +1108,13 @@ static int vxlan_newlink(struct net *net
 	if (data[IFLA_VXLAN_LIMIT])
 		vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
 
+	if (data[IFLA_VXLAN_PORT_RANGE]) {
+		const struct ifla_vxlan_port_range *p
+			= nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+		vxlan->port_min = ntohs(p->low);
+		vxlan->port_max = ntohs(p->high);
+	}
+
 	err = register_netdevice(dev);
 	if (!err)
 		hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni));
@@ -1099,12 +1143,17 @@ static size_t vxlan_get_size(const struc
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_LEARNING */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_AGEING */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_LIMIT */
+		nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
 		0;
 }
 
 static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
 	const struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct ifla_vxlan_port_range ports = {
+		.low =  htons(vxlan->port_min),
+		.high = htons(vxlan->port_max),
+	};
 
 	if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni))
 		goto nla_put_failure;
@@ -1125,6 +1174,9 @@ static int vxlan_fill_info(struct sk_buf
 	    nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
 		goto nla_put_failure;
 
+	if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
+		goto nla_put_failure;
+
 	return 0;
 
 nla_put_failure:
--- a/include/linux/if_link.h	2012-10-09 10:35:01.403159162 -0700
+++ b/include/linux/if_link.h	2012-10-09 10:49:08.238763697 -0700
@@ -284,10 +284,16 @@ enum {
 	IFLA_VXLAN_LEARNING,
 	IFLA_VXLAN_AGEING,
 	IFLA_VXLAN_LIMIT,
+	IFLA_VXLAN_PORT_RANGE,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
 
+struct ifla_vxlan_port_range {
+	__be16	low;
+	__be16	high;
+};
+
 /* SR-IOV virtual function management section */
 
 enum {

^ permalink raw reply

* [PATCH 6/6] vxlan: fix receive checksum handling
From: Stephen Hemminger @ 2012-10-09 17:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20121009175637.048993312@vyatta.com>

[-- Attachment #1: vxlan-checksum.patch --]
[-- Type: text/plain, Size: 1198 bytes --]

The VXLAN drive was trying to use postpull_rcsum to allow receive checksum
offload to work on drivers using CHECKSUM_COMPLETE method. But this
doesn't work correctly. Just force full receive checksum on received
packet.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/drivers/net/vxlan.c	2012-10-09 10:49:19.830648777 -0700
+++ b/drivers/net/vxlan.c	2012-10-09 10:49:30.982538112 -0700
@@ -537,7 +537,6 @@ static int vxlan_udp_encap_recv(struct s
 	}
 
 	__skb_pull(skb, sizeof(struct vxlanhdr));
-	skb_postpull_rcsum(skb, eth_hdr(skb), sizeof(struct vxlanhdr));
 
 	/* Is this VNI defined? */
 	vni = ntohl(vxh->vx_vni) >> 8;
@@ -556,7 +555,6 @@ static int vxlan_udp_encap_recv(struct s
 	/* Re-examine inner Ethernet packet */
 	oip = ip_hdr(skb);
 	skb->protocol = eth_type_trans(skb, vxlan->dev);
-	skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
 
 	/* Ignore packet loops (and multicast echo) */
 	if (compare_ether_addr(eth_hdr(skb)->h_source,
@@ -568,6 +566,7 @@ static int vxlan_udp_encap_recv(struct s
 
 	__skb_tunnel_rx(skb, vxlan->dev);
 	skb_reset_network_header(skb);
+	skb->ip_summed = CHECKSUM_NONE;
 
 	err = IP_ECN_decapsulate(oip, skb);
 	if (unlikely(err)) {

^ permalink raw reply

* [PATCH 1/6] vxlan: minor output refactoring
From: Stephen Hemminger @ 2012-10-09 17:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20121009175637.048993312@vyatta.com>

[-- Attachment #1: vxlan-dst.patch --]
[-- Type: text/plain, Size: 1722 bytes --]

Move code to find destination to a small function.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/drivers/net/vxlan.c	2012-10-09 10:34:57.000000000 -0700
+++ b/drivers/net/vxlan.c	2012-10-09 10:48:56.546879617 -0700
@@ -621,6 +621,18 @@ static inline u8 vxlan_ecn_encap(u8 tos,
 	return INET_ECN_encapsulate(tos, inner);
 }
 
+static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+	const struct ethhdr *eth = (struct ethhdr *) skb->data;
+	struct vxlan_fdb *f;
+
+	if (is_multicast_ether_addr(eth->h_dest) ||
+	    (f = vxlan_find_mac(vxlan, eth->h_dest)) == NULL)
+		return vxlan->gaddr;
+	else
+		return f->remote_ip;
+}
+
 /* Transmit local packets over Vxlan
  *
  * Outer IP header inherits ECN and DF from inner header.
@@ -632,13 +644,11 @@ static netdev_tx_t vxlan_xmit(struct sk_
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct rtable *rt;
-	const struct ethhdr *eth;
 	const struct iphdr *old_iph;
 	struct iphdr *iph;
 	struct vxlanhdr *vxh;
 	struct udphdr *uh;
 	struct flowi4 fl4;
-	struct vxlan_fdb *f;
 	unsigned int pkt_len = skb->len;
 	u32 hash;
 	__be32 dst;
@@ -646,21 +656,16 @@ static netdev_tx_t vxlan_xmit(struct sk_
 	__u8 tos, ttl;
 	int err;
 
+	dst = vxlan_find_dst(vxlan, skb);
+	if (!dst)
+		goto drop;
+
 	/* Need space for new headers (invalidates iph ptr) */
 	if (skb_cow_head(skb, VXLAN_HEADROOM))
 		goto drop;
 
-	eth = (void *)skb->data;
 	old_iph = ip_hdr(skb);
 
-	if (!is_multicast_ether_addr(eth->h_dest) &&
-	    (f = vxlan_find_mac(vxlan, eth->h_dest)))
-		dst = f->remote_ip;
-	else if (vxlan->gaddr) {
-		dst = vxlan->gaddr;
-	} else
-		goto drop;
-
 	ttl = vxlan->ttl;
 	if (!ttl && IN_MULTICAST(ntohl(dst)))
 		ttl = 1;

^ permalink raw reply


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