* [PATCHv2 net-next 09/11] net: mvpp2: simplify MVPP2_PRS_RI_* definitions
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
Some of the MVPP2_PRS_RI_* definitions use the ~(value) syntax, which
doesn't compile nicely on 64-bit. Moreover, those definitions are in
fact unneeded, since they are always used in combination with a bit
mask that ensures only the appropriate bits are modified.
Therefore, such definitions should just be set to 0x0. For example:
#define MVPP2_PRS_RI_L2_CAST_MASK 0x600
#define MVPP2_PRS_RI_L2_UCAST ~(BIT(9) | BIT(10))
#define MVPP2_PRS_RI_L2_MCAST BIT(9)
#define MVPP2_PRS_RI_L2_BCAST BIT(10)
becomes
#define MVPP2_PRS_RI_L2_CAST_MASK 0x600
#define MVPP2_PRS_RI_L2_UCAST 0x0
#define MVPP2_PRS_RI_L2_MCAST BIT(9)
#define MVPP2_PRS_RI_L2_BCAST BIT(10)
Because the values (MVPP2_PRS_RI_L2_UCAST, MVPP2_PRS_RI_L2_MCAST and
MVPP2_PRS_RI_L2_BCAST) are always applied with
MVPP2_PRS_RI_L2_CAST_MASK, and therefore there is no need for
MVPP2_PRS_RI_L2_UCAST to be defined as ~(BIT(9) | BIT(10)).
It fixes the following warnings when building the driver on a 64-bit
platform (which is not possible as of this commit, but will be enabled
in a follow-up commit):
drivers/net/ethernet/marvell/mvpp2.c: In function ‘mvpp2_prs_mac_promisc_set’:
drivers/net/ethernet/marvell/mvpp2.c:524:33: warning: large integer implicitly truncated to unsigned type [-Woverflow]
#define MVPP2_PRS_RI_L2_UCAST ~(BIT(9) | BIT(10))
^
drivers/net/ethernet/marvell/mvpp2.c:1459:33: note: in expansion of macro ‘MVPP2_PRS_RI_L2_UCAST’
mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_UCAST,
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 36c73dc..58cf9af 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -511,19 +511,19 @@ enum mvpp2_tag_type {
#define MVPP2_PRS_RI_MAC_ME_MASK 0x1
#define MVPP2_PRS_RI_DSA_MASK 0x2
#define MVPP2_PRS_RI_VLAN_MASK 0xc
-#define MVPP2_PRS_RI_VLAN_NONE ~(BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_VLAN_NONE 0x0
#define MVPP2_PRS_RI_VLAN_SINGLE BIT(2)
#define MVPP2_PRS_RI_VLAN_DOUBLE BIT(3)
#define MVPP2_PRS_RI_VLAN_TRIPLE (BIT(2) | BIT(3))
#define MVPP2_PRS_RI_CPU_CODE_MASK 0x70
#define MVPP2_PRS_RI_CPU_CODE_RX_SPEC BIT(4)
#define MVPP2_PRS_RI_L2_CAST_MASK 0x600
-#define MVPP2_PRS_RI_L2_UCAST ~(BIT(9) | BIT(10))
+#define MVPP2_PRS_RI_L2_UCAST 0x0
#define MVPP2_PRS_RI_L2_MCAST BIT(9)
#define MVPP2_PRS_RI_L2_BCAST BIT(10)
#define MVPP2_PRS_RI_PPPOE_MASK 0x800
#define MVPP2_PRS_RI_L3_PROTO_MASK 0x7000
-#define MVPP2_PRS_RI_L3_UN ~(BIT(12) | BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_UN 0x0
#define MVPP2_PRS_RI_L3_IP4 BIT(12)
#define MVPP2_PRS_RI_L3_IP4_OPT BIT(13)
#define MVPP2_PRS_RI_L3_IP4_OTHER (BIT(12) | BIT(13))
@@ -531,7 +531,7 @@ enum mvpp2_tag_type {
#define MVPP2_PRS_RI_L3_IP6_EXT (BIT(12) | BIT(14))
#define MVPP2_PRS_RI_L3_ARP (BIT(13) | BIT(14))
#define MVPP2_PRS_RI_L3_ADDR_MASK 0x18000
-#define MVPP2_PRS_RI_L3_UCAST ~(BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_L3_UCAST 0x0
#define MVPP2_PRS_RI_L3_MCAST BIT(15)
#define MVPP2_PRS_RI_L3_BCAST (BIT(15) | BIT(16))
#define MVPP2_PRS_RI_IP_FRAG_MASK 0x20000
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 11/11] net: mvpp2: enable building on 64-bit platforms
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
The mvpp2 is going to be extended to support the Marvell Armada 7K/8K
platform, which is ARM64. As a preparation to this work, this commit
enables building the mvpp2 driver on ARM64, by:
- Adjusting the Kconfig dependency
- Fixing the types used in the driver so that they are 32/64-bits
compliant. We use dma_addr_t for DMA addresses, and unsigned long
for virtual addresses.
It is worth mentioning that after this commit, the driver is for now
still only used on 32-bits platforms.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/Kconfig | 3 +--
drivers/net/ethernet/marvell/mvpp2.c | 29 +++++++++++++++++------------
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index f4b7cf1..d2555e8b 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -83,9 +83,8 @@ config MVNETA_BM
config MVPP2
tristate "Marvell Armada 375 network interface support"
- depends on MACH_ARMADA_375 || COMPILE_TEST
+ depends on ARCH_MVEBU || COMPILE_TEST
depends on HAS_DMA
- depends on !64BIT
select MVMDIO
---help---
This driver supports the network interface units in the
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 1e08e8f..2268808 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3388,7 +3388,8 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,
if (!bm_pool->virt_addr)
return -ENOMEM;
- if (!IS_ALIGNED((u32)bm_pool->virt_addr, MVPP2_BM_POOL_PTR_ALIGN)) {
+ if (!IS_ALIGNED((unsigned long)bm_pool->virt_addr,
+ MVPP2_BM_POOL_PTR_ALIGN)) {
dma_free_coherent(&pdev->dev, size_bytes, bm_pool->virt_addr,
bm_pool->phys_addr);
dev_err(&pdev->dev, "BM pool %d is not %d bytes aligned\n",
@@ -3433,7 +3434,7 @@ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
for (i = 0; i < bm_pool->buf_num; i++) {
dma_addr_t buf_phys_addr;
- u32 vaddr;
+ unsigned long vaddr;
/* Get buffer virtual address (indirect access) */
buf_phys_addr = mvpp2_read(priv,
@@ -3596,14 +3597,15 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
}
/* Get pool number from a BM cookie */
-static inline int mvpp2_bm_cookie_pool_get(u32 cookie)
+static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie)
{
return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
}
/* Release buffer to BM */
static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
- u32 buf_phys_addr, u32 buf_virt_addr)
+ dma_addr_t buf_phys_addr,
+ unsigned long buf_virt_addr)
{
mvpp2_write(port->priv, MVPP2_BM_VIRT_RLS_REG, buf_virt_addr);
mvpp2_write(port->priv, MVPP2_BM_PHY_RLS_REG(pool), buf_phys_addr);
@@ -3611,7 +3613,8 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
/* Release multicast buffer */
static void mvpp2_bm_pool_mc_put(struct mvpp2_port *port, int pool,
- u32 buf_phys_addr, u32 buf_virt_addr,
+ dma_addr_t buf_phys_addr,
+ unsigned long buf_virt_addr,
int mc_id)
{
u32 val = 0;
@@ -3626,7 +3629,8 @@ static void mvpp2_bm_pool_mc_put(struct mvpp2_port *port, int pool,
/* Refill BM pool */
static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
- u32 phys_addr, u32 cookie)
+ dma_addr_t phys_addr,
+ unsigned long cookie)
{
int pool = mvpp2_bm_cookie_pool_get(bm);
@@ -3657,7 +3661,8 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
if (!buf)
break;
- mvpp2_bm_pool_put(port, bm_pool->id, (u32)phys_addr, (u32)buf);
+ mvpp2_bm_pool_put(port, bm_pool->id, phys_addr,
+ (unsigned long)buf);
}
/* Update BM driver with number of buffers added to pool */
@@ -5015,7 +5020,7 @@ static int mvpp2_rx_refill(struct mvpp2_port *port,
if (!buf)
return -ENOMEM;
- mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)buf);
+ mvpp2_pool_refill(port, bm, phys_addr, (unsigned long)buf);
return 0;
}
@@ -5057,10 +5062,10 @@ static void mvpp2_buff_hdr_rx(struct mvpp2_port *port,
struct mvpp2_buff_hdr *buff_hdr;
struct sk_buff *skb;
u32 rx_status = rx_desc->status;
- u32 buff_phys_addr;
- u32 buff_virt_addr;
- u32 buff_phys_addr_next;
- u32 buff_virt_addr_next;
+ dma_addr_t buff_phys_addr;
+ unsigned long buff_virt_addr;
+ dma_addr_t buff_phys_addr_next;
+ unsigned long buff_virt_addr_next;
int mc_id;
int pool_id;
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 10/11] net: mvpp2: switch to build_skb() in the RX path
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
This commit adapts the mvpp2 RX path to use the build_skb() method. Not
only build_skb() is now the recommended mechanism, but it also
simplifies the addition of support for the PPv2.2 variant.
Indeed, without build_skb(), we have to keep track for each RX
descriptor of the physical address of the packet buffer, and the virtual
address of the SKB. However, in PPv2.2 running on 64 bits platform,
there is not enough space in the descriptor to store the virtual address
of the SKB. So having to take care only of the address of the packet
buffer, and building the SKB upon reception helps in supporting PPv2.2.
The implementation is fairly straightforward:
- mvpp2_skb_alloc() is renamed to mvpp2_buf_alloc() and no longer
allocates a SKB. Instead, it allocates a buffer using the new
mvpp2_frag_alloc() function, with enough space for the data and SKB.
- The initialization of the RX buffers in mvpp2_bm_bufs_add() as well
as the refill of the RX buffers in mvpp2_rx_refill() is adjusted
accordingly.
- Finally, the mvpp2_rx() is modified to use build_skb().
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 77 +++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 58cf9af..1e08e8f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -918,6 +918,7 @@ struct mvpp2_bm_pool {
int buf_size;
/* Packet size */
int pkt_size;
+ int frag_size;
/* BPPE virtual base address */
u32 *virt_addr;
@@ -3354,6 +3355,22 @@ static void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
}
+static void *mvpp2_frag_alloc(const struct mvpp2_bm_pool *pool)
+{
+ if (likely(pool->frag_size <= PAGE_SIZE))
+ return netdev_alloc_frag(pool->frag_size);
+ else
+ return kmalloc(pool->frag_size, GFP_ATOMIC);
+}
+
+static void mvpp2_frag_free(const struct mvpp2_bm_pool *pool, void *data)
+{
+ if (likely(pool->frag_size <= PAGE_SIZE))
+ skb_free_frag(data);
+ else
+ kfree(data);
+}
+
/* Buffer Manager configuration routines */
/* Create pool */
@@ -3428,7 +3445,8 @@ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
if (!vaddr)
break;
- dev_kfree_skb_any((struct sk_buff *)vaddr);
+
+ mvpp2_frag_free(bm_pool, (void *)vaddr);
}
/* Update BM driver with number of buffers removed from pool */
@@ -3542,29 +3560,28 @@ static void mvpp2_rxq_short_pool_set(struct mvpp2_port *port,
mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
}
-/* Allocate skb for BM pool */
-static struct sk_buff *mvpp2_skb_alloc(struct mvpp2_port *port,
- struct mvpp2_bm_pool *bm_pool,
- dma_addr_t *buf_phys_addr,
- gfp_t gfp_mask)
+static void *mvpp2_buf_alloc(struct mvpp2_port *port,
+ struct mvpp2_bm_pool *bm_pool,
+ dma_addr_t *buf_phys_addr,
+ gfp_t gfp_mask)
{
- struct sk_buff *skb;
dma_addr_t phys_addr;
+ void *data;
- skb = __dev_alloc_skb(bm_pool->pkt_size, gfp_mask);
- if (!skb)
+ data = mvpp2_frag_alloc(bm_pool);
+ if (!data)
return NULL;
- phys_addr = dma_map_single(port->dev->dev.parent, skb->head,
+ phys_addr = dma_map_single(port->dev->dev.parent, data,
MVPP2_RX_BUF_SIZE(bm_pool->pkt_size),
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(port->dev->dev.parent, phys_addr))) {
- dev_kfree_skb_any(skb);
+ mvpp2_frag_free(bm_pool, data);
return NULL;
}
*buf_phys_addr = phys_addr;
- return skb;
+ return data;
}
/* Set pool number in a BM cookie */
@@ -3620,9 +3637,9 @@ static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
struct mvpp2_bm_pool *bm_pool, int buf_num)
{
- struct sk_buff *skb;
int i, buf_size, total_size;
dma_addr_t phys_addr;
+ void *buf;
buf_size = MVPP2_RX_BUF_SIZE(bm_pool->pkt_size);
total_size = MVPP2_RX_TOTAL_SIZE(buf_size);
@@ -3636,11 +3653,11 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
}
for (i = 0; i < buf_num; i++) {
- skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_KERNEL);
- if (!skb)
+ buf = mvpp2_buf_alloc(port, bm_pool, &phys_addr, GFP_KERNEL);
+ if (!buf)
break;
- mvpp2_bm_pool_put(port, bm_pool->id, (u32)phys_addr, (u32)skb);
+ mvpp2_bm_pool_put(port, bm_pool->id, (u32)phys_addr, (u32)buf);
}
/* Update BM driver with number of buffers added to pool */
@@ -3696,6 +3713,9 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
port->priv, new_pool);
new_pool->pkt_size = pkt_size;
+ new_pool->frag_size =
+ SKB_DATA_ALIGN(MVPP2_RX_BUF_SIZE(pkt_size)) +
+ MVPP2_SKB_SHINFO_SIZE;
/* Allocate buffers for this pool */
num = mvpp2_bm_bufs_add(port, new_pool, pkts_num);
@@ -4987,15 +5007,15 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
static int mvpp2_rx_refill(struct mvpp2_port *port,
struct mvpp2_bm_pool *bm_pool, u32 bm)
{
- struct sk_buff *skb;
dma_addr_t phys_addr;
+ void *buf;
/* No recycle or too many buffers are in use, so allocate a new skb */
- skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_ATOMIC);
- if (!skb)
+ buf = mvpp2_buf_alloc(port, bm_pool, &phys_addr, GFP_ATOMIC);
+ if (!buf)
return -ENOMEM;
- mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+ mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)buf);
return 0;
}
@@ -5087,14 +5107,17 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
struct mvpp2_bm_pool *bm_pool;
struct sk_buff *skb;
+ unsigned int frag_size;
dma_addr_t phys_addr;
u32 bm, rx_status;
int pool, rx_bytes, err;
+ void *data;
rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
phys_addr = rx_desc->buf_phys_addr;
+ data = (void *)rx_desc->buf_cookie;
bm = mvpp2_bm_cookie_build(rx_desc);
pool = mvpp2_bm_cookie_pool_get(bm);
@@ -5115,12 +5138,22 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
+
mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
rx_desc->buf_cookie);
continue;
}
- skb = (struct sk_buff *)rx_desc->buf_cookie;
+ if (bm_pool->frag_size > PAGE_SIZE)
+ frag_size = 0;
+ else
+ frag_size = bm_pool->frag_size;
+
+ skb = build_skb(data, frag_size);
+ if (!skb) {
+ netdev_warn(port->dev, "skb build failed\n");
+ goto err_drop_frame;
+ }
err = mvpp2_rx_refill(port, bm_pool, bm);
if (err) {
@@ -5134,7 +5167,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
rcvd_pkts++;
rcvd_bytes += rx_bytes;
- skb_reserve(skb, MVPP2_MH_SIZE);
+ skb_reserve(skb, MVPP2_MH_SIZE + NET_SKB_PAD);
skb_put(skb, rx_bytes);
skb->protocol = eth_type_trans(skb, dev);
mvpp2_rx_csum(port, rx_status, skb);
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 05/11] net: mvpp2: drop useless fields in mvpp2_bm_pool and related code
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
This commit drops dead code from the mvpp2 driver. The 'in_use' and
'in_use_thresh' fields of 'struct mvpp2_bm_pool' are
incremented/decremented/initialized in various places. But they are only
used in one place:
if (is_recycle &&
(atomic_read(&bm_pool->in_use) < bm_pool->in_use_thresh))
return 0;
However 'is_recycle', passed as argument to mvpp2_rx_refill() is always
false. So in fact, this code is never reached, and the 'is_recycle'
argument is useless. So let's drop this code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 18 +++---------------
1 file changed, 3 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 6720cdac..bfa9f77 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -930,10 +930,6 @@ struct mvpp2_bm_pool {
/* Ports using BM pool */
u32 port_map;
-
- /* Occupied buffers indicator */
- atomic_t in_use;
- int in_use_thresh;
};
struct mvpp2_buff_hdr {
@@ -3399,7 +3395,6 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,
bm_pool->size = size;
bm_pool->pkt_size = 0;
bm_pool->buf_num = 0;
- atomic_set(&bm_pool->in_use, 0);
return 0;
}
@@ -3656,7 +3651,6 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
/* Update BM driver with number of buffers added to pool */
bm_pool->buf_num += i;
- bm_pool->in_use_thresh = bm_pool->buf_num / 4;
netdev_dbg(port->dev,
"%s pool %d: pkt_size=%4d, buf_size=%4d, total_size=%4d\n",
@@ -4997,23 +4991,18 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
/* Reuse skb if possible, or allocate a new skb and add it to BM pool */
static int mvpp2_rx_refill(struct mvpp2_port *port,
- struct mvpp2_bm_pool *bm_pool,
- u32 bm, int is_recycle)
+ struct mvpp2_bm_pool *bm_pool, u32 bm)
{
struct sk_buff *skb;
dma_addr_t phys_addr;
- if (is_recycle &&
- (atomic_read(&bm_pool->in_use) < bm_pool->in_use_thresh))
- return 0;
-
/* No recycle or too many buffers are in use, so allocate a new skb */
skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
- atomic_dec(&bm_pool->in_use);
+
return 0;
}
@@ -5139,7 +5128,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
skb = (struct sk_buff *)rx_desc->buf_cookie;
- err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+ err = mvpp2_rx_refill(port, bm_pool, bm);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
goto err_drop_frame;
@@ -5150,7 +5139,6 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
rcvd_pkts++;
rcvd_bytes += rx_bytes;
- atomic_inc(&bm_pool->in_use);
skb_reserve(skb, MVPP2_MH_SIZE);
skb_put(skb, rx_bytes);
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 08/11] net: mvpp2: fix indentation of MVPP2_EXT_GLOBAL_CTRL_DEFAULT
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index edffcc1..36c73dc 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -254,7 +254,7 @@
#define MVPP2_PHY_AN_CFG0_REG 0x34
#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
#define MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG 0x305c
-#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
+#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
/* Per-port registers */
#define MVPP2_GMAC_CTRL_0_REG 0x0
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 07/11] net: mvpp2: remove unused register definitions
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 8174f40..edffcc1 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -253,10 +253,6 @@
#define MVPP2_SRC_ADDR_HIGH 0x28
#define MVPP2_PHY_AN_CFG0_REG 0x34
#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
-#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \
- 0x400 + (port) * 0x400)
-#define MVPP2_MIB_LATE_COLLISION 0x7c
-#define MVPP2_ISR_SUM_MASK_REG 0x220c
#define MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG 0x305c
#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 06/11] net: mvpp2: simplify mvpp2_bm_bufs_add()
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
The mvpp2_bm_bufs_add() currently creates a fake cookie by calling
mvpp2_bm_cookie_pool_set(), just to be able to call
mvpp2_pool_refill(). But all what mvpp2_pool_refill() does is extract
the pool ID from the cookie, and call mvpp2_bm_pool_put() with this ID.
Instead of doing this convoluted thing, just call mvpp2_bm_pool_put()
directly, since we have the BM pool ID.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index bfa9f77..8174f40 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3626,7 +3626,6 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
{
struct sk_buff *skb;
int i, buf_size, total_size;
- u32 bm;
dma_addr_t phys_addr;
buf_size = MVPP2_RX_BUF_SIZE(bm_pool->pkt_size);
@@ -3640,13 +3639,12 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
return 0;
}
- bm = mvpp2_bm_cookie_pool_set(0, bm_pool->id);
for (i = 0; i < buf_num; i++) {
skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_KERNEL);
if (!skb)
break;
- mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+ mvpp2_bm_pool_put(port, bm_pool->id, (u32)phys_addr, (u32)skb);
}
/* Update BM driver with number of buffers added to pool */
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 01/11] net: mvpp2: handle too large value handling in mvpp2_rx_pkts_coal_set()
From: Thomas Petazzoni @ 2016-12-28 16:45 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
Currently, mvpp2_rx_pkts_coal_set() does the following to avoid setting
a too large value for the RX coalescing by packet number:
val = (pkts & MVPP2_OCCUPIED_THRESH_MASK);
This means that if you set a value that is slightly higher the the
maximum number of packets, you in fact get a very low value. It makes a
lot more sense to simply check if the value is too high, and if it's too
high, limit it to the maximum possible value.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 4fe430c..02d91e4 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -4381,11 +4381,11 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
struct mvpp2_rx_queue *rxq, u32 pkts)
{
- u32 val;
+ if (pkts > MVPP2_OCCUPIED_THRESH_MASK)
+ pkts = MVPP2_OCCUPIED_THRESH_MASK;
- val = (pkts & MVPP2_OCCUPIED_THRESH_MASK);
mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
- mvpp2_write(port->priv, MVPP2_RXQ_THRESH_REG, val);
+ mvpp2_write(port->priv, MVPP2_RXQ_THRESH_REG, pkts);
rxq->pkts_coal = pkts;
}
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 02/11] net: mvpp2: handle too large value in mvpp2_rx_time_coal_set()
From: Thomas Petazzoni @ 2016-12-28 16:45 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
When configuring the MVPP2_ISR_RX_THRESHOLD_REG with the RX coalescing
time threshold, we do not check for the maximum allowed value supported
by the driver, which means we might overflow and use a bogus value. This
commit adds a check for this situation, and if a value higher than what
is supported by the hardware is provided, then we use the maximum value
supported by the hardware.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 02d91e4..a1ba89f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -154,6 +154,7 @@
/* Interrupt Cause and Mask registers */
#define MVPP2_ISR_RX_THRESHOLD_REG(rxq) (0x5200 + 4 * (rxq))
+#define MVPP2_MAX_ISR_RX_THRESHOLD 0xfffff0
#define MVPP2_ISR_RXQ_GROUP_REG(rxq) (0x5400 + 4 * (rxq))
#define MVPP2_ISR_ENABLE_REG(port) (0x5420 + 4 * (port))
#define MVPP2_ISR_ENABLE_INTERRUPT(mask) ((mask) & 0xffff)
@@ -4397,6 +4398,12 @@ static void mvpp2_rx_time_coal_set(struct mvpp2_port *port,
u32 val;
val = (port->priv->tclk / USEC_PER_SEC) * usec;
+
+ if (val > MVPP2_MAX_ISR_RX_THRESHOLD) {
+ val = MVPP2_MAX_ISR_RX_THRESHOLD;
+ usec = (val * USEC_PER_SEC) / port->priv->tclk;
+ }
+
mvpp2_write(port->priv, MVPP2_ISR_RX_THRESHOLD_REG(rxq->id), val);
rxq->time_coal = usec;
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 04/11] net: mvpp2: remove unused 'tx_skb' field of 'struct mvpp2_tx_queue'
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
This commit remove a field of 'struct mvpp2_tx_queue' that is not used
anywhere.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index d098c7b..6720cdac 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -823,9 +823,6 @@ struct mvpp2_tx_queue {
/* Per-CPU control of physical Tx queues */
struct mvpp2_txq_pcpu __percpu *pcpu;
- /* Array of transmitted skb */
- struct sk_buff **tx_skb;
-
u32 done_pkts_coal;
/* Virtual address of thex Tx DMA descriptors array */
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 00/11] net: mvpp2: misc improvements and preparation patches
From: Thomas Petazzoni @ 2016-12-28 16:45 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
Hello,
This series contains a number of misc improvements and preparation
patches for an upcoming series that adds support for the new PPv2.2
network controller to the mvpp2 driver.
The most significant improvements are:
- Switching to using build_skb(), which is necessary for the upcoming
PPv2.2 support, but anyway a good improvement to the current mvpp2
driver (supporting PPv2.1).
- Making the driver build on 64-bit platforms.
Changes since v1:
- This series is split as a separate series from the larger patch set
adding support for PPv2.2 in the mvpp2 driver, as requested by
David Miller.
- Rebased on top of v4.10-rc1.
Thanks!
Thomas
Thomas Petazzoni (11):
net: mvpp2: handle too large value handling in
mvpp2_rx_pkts_coal_set()
net: mvpp2: handle too large value in mvpp2_rx_time_coal_set()
net: mvpp2: release reference to txq_cpu[] entry after unmapping
net: mvpp2: remove unused 'tx_skb' field of 'struct mvpp2_tx_queue'
net: mvpp2: drop useless fields in mvpp2_bm_pool and related code
net: mvpp2: simplify mvpp2_bm_bufs_add()
net: mvpp2: remove unused register definitions
net: mvpp2: fix indentation of MVPP2_EXT_GLOBAL_CTRL_DEFAULT
net: mvpp2: simplify MVPP2_PRS_RI_* definitions
net: mvpp2: switch to build_skb() in the RX path
net: mvpp2: enable building on 64-bit platforms
drivers/net/ethernet/marvell/Kconfig | 3 +-
drivers/net/ethernet/marvell/mvpp2.c | 161 ++++++++++++++++++++---------------
2 files changed, 93 insertions(+), 71 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCHv2 net-next 03/11] net: mvpp2: release reference to txq_cpu[] entry after unmapping
From: Thomas Petazzoni @ 2016-12-28 16:45 UTC (permalink / raw)
To: netdev, David S. Miller
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak, linux-arm-kernel,
Stefan Chulski, Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943567-12483-1-git-send-email-thomas.petazzoni@free-electrons.com>
The mvpp2_txq_bufs_free() function is called upon TX completion to DMA
unmap TX buffers, and free the corresponding SKBs. It gets the
references to the SKB to free and the DMA buffer to unmap from a per-CPU
txq_pcpu data structure.
However, the code currently increments the pointer to the next entry
before doing the DMA unmap and freeing the SKB. It does not cause any
visible problem because for a given SKB the TX completion is guaranteed
to take place on the CPU where the TX was started. However, it is much
more logical to increment the pointer to the next entry once the current
entry has been completely unmapped/released.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index a1ba89f..d098c7b 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -4420,13 +4420,12 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
struct mvpp2_txq_pcpu_buf *tx_buf =
txq_pcpu->buffs + txq_pcpu->txq_get_index;
- mvpp2_txq_inc_get(txq_pcpu);
-
dma_unmap_single(port->dev->dev.parent, tx_buf->phys,
tx_buf->size, DMA_TO_DEVICE);
- if (!tx_buf->skb)
- continue;
- dev_kfree_skb_any(tx_buf->skb);
+ if (tx_buf->skb)
+ dev_kfree_skb_any(tx_buf->skb);
+
+ mvpp2_txq_inc_get(txq_pcpu);
}
}
--
2.7.4
^ permalink raw reply related
* [PATCHv2 net-next 07/16] net: mvpp2: adapt the mvpp2_rxq_*_pool_set functions to PPv2.2
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Stefan Chulski,
Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943592-12556-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The MVPP2_RXQ_CONFIG_REG register has a slightly different layout
between PPv2.1 and PPv2.2, so this commit adapts the functions modifying
this register to accommodate for both the PPv2.1 and PPv2.2 cases.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/net/ethernet/marvell/mvpp2.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 160b787..8fc818d 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -50,9 +50,11 @@
#define MVPP2_SNOOP_PKT_SIZE_MASK 0x1ff
#define MVPP2_SNOOP_BUF_HDR_MASK BIT(9)
#define MVPP2_RXQ_POOL_SHORT_OFFS 20
-#define MVPP2_RXQ_POOL_SHORT_MASK 0x700000
+#define MVPP21_RXQ_POOL_SHORT_MASK 0x700000
+#define MVPP22_RXQ_POOL_SHORT_MASK 0xf00000
#define MVPP2_RXQ_POOL_LONG_OFFS 24
-#define MVPP2_RXQ_POOL_LONG_MASK 0x7000000
+#define MVPP21_RXQ_POOL_LONG_MASK 0x7000000
+#define MVPP22_RXQ_POOL_LONG_MASK 0xf000000
#define MVPP2_RXQ_PACKET_OFFSET_OFFS 28
#define MVPP2_RXQ_PACKET_OFFSET_MASK 0x70000000
#define MVPP2_RXQ_DISABLE_MASK BIT(31)
@@ -3762,17 +3764,20 @@ static int mvpp2_bm_init(struct platform_device *pdev, struct mvpp2 *priv)
static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
int lrxq, int long_pool)
{
- u32 val;
+ u32 val, mask;
int prxq;
/* Get queue physical ID */
prxq = port->rxqs[lrxq]->id;
- val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
- val &= ~MVPP2_RXQ_POOL_LONG_MASK;
- val |= ((long_pool << MVPP2_RXQ_POOL_LONG_OFFS) &
- MVPP2_RXQ_POOL_LONG_MASK);
+ if (port->priv->hw_version == MVPP21)
+ mask = MVPP21_RXQ_POOL_LONG_MASK;
+ else
+ mask = MVPP22_RXQ_POOL_LONG_MASK;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~mask;
+ val |= (long_pool << MVPP2_RXQ_POOL_LONG_OFFS) & mask;
mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
}
@@ -3780,17 +3785,20 @@ static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
static void mvpp2_rxq_short_pool_set(struct mvpp2_port *port,
int lrxq, int short_pool)
{
- u32 val;
+ u32 val, mask;
int prxq;
/* Get queue physical ID */
prxq = port->rxqs[lrxq]->id;
- val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
- val &= ~MVPP2_RXQ_POOL_SHORT_MASK;
- val |= ((short_pool << MVPP2_RXQ_POOL_SHORT_OFFS) &
- MVPP2_RXQ_POOL_SHORT_MASK);
+ if (port->priv->hw_version == MVPP21)
+ mask = MVPP21_RXQ_POOL_SHORT_MASK;
+ else
+ mask = MVPP22_RXQ_POOL_SHORT_MASK;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~mask;
+ val |= (short_pool << MVPP2_RXQ_POOL_SHORT_OFFS) & mask;
mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
}
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCHv2 net-next 03/16] net: mvpp2: add hw_version field in "struct mvpp2"
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Stefan Chulski,
Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943592-12556-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
In preparation to the introduction for the support of PPv2.2 in the
mvpp2 driver, this commit adds a hw_version field to the struct
mvpp2, and uses the .data field of the DT match table to fill it in.
Having the MVPP21 and MVPP22 definitions available will allow to start
adding the necessary conditional code to support PPv2.2.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/net/ethernet/marvell/mvpp2.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index fd84923..bc359a9 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -25,6 +25,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/phy.h>
#include <linux/clk.h>
#include <linux/hrtimer.h>
@@ -649,6 +650,9 @@ struct mvpp2 {
/* Tclk value */
u32 tclk;
+
+ /* HW version */
+ enum { MVPP21, MVPP22 } hw_version;
};
struct mvpp2_pcpu_stats {
@@ -6480,6 +6484,9 @@ static int mvpp2_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->hw_version =
+ (unsigned long)of_device_get_match_data(&pdev->dev);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->base))
@@ -6584,7 +6591,10 @@ static int mvpp2_remove(struct platform_device *pdev)
}
static const struct of_device_id mvpp2_match[] = {
- { .compatible = "marvell,armada-375-pp2" },
+ {
+ .compatible = "marvell,armada-375-pp2",
+ .data = (void *)MVPP21,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, mvpp2_match);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCHv2 net-next 02/16] net: mvpp2: add and use accessors for TX/RX descriptors
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Stefan Chulski,
Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943592-12556-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The PPv2.2 IP has a different TX and RX descriptor layout compared to
PPv2.1. In order to prepare for the introduction of PPv2.2 support in
mvpp2, this commit adds accessors for the different fields of the TX
and RX descriptors, and changes the code to use them.
For now, the mvpp2_port argument passed to the accessors is not used,
but it will be used in follow-up to update the descriptor according to
the version of the IP being used.
Apart from the mechanical changes to use the newly introduced
accessors, a few other changes, needed to use the accessors, are made:
- The mvpp2_txq_inc_put() function now takes a mvpp2_port as first
argument, as it is needed to use the accessors.
- Similarly, the mvpp2_bm_cookie_build() gains a mvpp2_port first
argument, for the same reason.
- In mvpp2_rx_error(), instead of accessing the RX descriptor in each
case of the switch, we introduce a local variable to store the
packet size.
- Similarly, in mvpp2_buff_hdr_rx(), we introduce a local "cookie"
variable to store the RX descriptor cookie, rather than accessing
it from the descriptor each time.
- In mvpp2_tx_frag_process() and mvpp2_tx() instead of accessing the
packet size from the TX descriptor, we use the actual value
available in the function, which is used to set the TX descriptor
packet size a few lines before.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/net/ethernet/marvell/mvpp2.c | 187 +++++++++++++++++++++++++----------
1 file changed, 137 insertions(+), 50 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 2268808..fd84923 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -967,6 +967,77 @@ static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)
return readl(priv->base + offset);
}
+static dma_addr_t mvpp2_txdesc_phys_addr_get(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc)
+{
+ return tx_desc->buf_phys_addr;
+}
+
+static void mvpp2_txdesc_phys_addr_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ dma_addr_t phys_addr)
+{
+ tx_desc->buf_phys_addr = phys_addr;
+}
+
+static size_t mvpp2_txdesc_size_get(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc)
+{
+ return tx_desc->data_size;
+}
+
+static void mvpp2_txdesc_size_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ size_t size)
+{
+ tx_desc->data_size = size;
+}
+
+static void mvpp2_txdesc_txq_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int txq)
+{
+ tx_desc->phys_txq = txq;
+}
+
+static void mvpp2_txdesc_cmd_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int command)
+{
+ tx_desc->command = command;
+}
+
+static void mvpp2_txdesc_offset_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int offset)
+{
+ tx_desc->packet_offset = offset;
+}
+
+static dma_addr_t mvpp2_rxdesc_phys_addr_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ return rx_desc->buf_phys_addr;
+}
+
+static unsigned long mvpp2_rxdesc_virt_addr_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ return rx_desc->buf_cookie;
+}
+
+static size_t mvpp2_rxdesc_size_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ return rx_desc->data_size;
+}
+
+static u32 mvpp2_rxdesc_status_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ return rx_desc->status;
+}
+
static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
{
txq_pcpu->txq_get_index++;
@@ -974,15 +1045,16 @@ static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
txq_pcpu->txq_get_index = 0;
}
-static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
+static void mvpp2_txq_inc_put(struct mvpp2_port *port,
+ struct mvpp2_txq_pcpu *txq_pcpu,
struct sk_buff *skb,
struct mvpp2_tx_desc *tx_desc)
{
struct mvpp2_txq_pcpu_buf *tx_buf =
txq_pcpu->buffs + txq_pcpu->txq_put_index;
tx_buf->skb = skb;
- tx_buf->size = tx_desc->data_size;
- tx_buf->phys = tx_desc->buf_phys_addr;
+ tx_buf->size = mvpp2_txdesc_size_get(port, tx_desc);
+ tx_buf->phys = mvpp2_txdesc_phys_addr_get(port, tx_desc);
txq_pcpu->txq_put_index++;
if (txq_pcpu->txq_put_index == txq_pcpu->size)
txq_pcpu->txq_put_index = 0;
@@ -4147,11 +4219,15 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
}
/* Obtain BM cookie information from descriptor */
-static u32 mvpp2_bm_cookie_build(struct mvpp2_rx_desc *rx_desc)
+static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
{
- int pool = (rx_desc->status & MVPP2_RXD_BM_POOL_ID_MASK) >>
- MVPP2_RXD_BM_POOL_ID_OFFS;
int cpu = smp_processor_id();
+ int pool;
+
+ pool = (mvpp2_rxdesc_status_get(port, rx_desc) &
+ MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
@@ -4580,10 +4656,11 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
for (i = 0; i < rx_received; i++) {
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
- u32 bm = mvpp2_bm_cookie_build(rx_desc);
+ u32 bm = mvpp2_bm_cookie_build(port, rx_desc);
- mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
- rx_desc->buf_cookie);
+ mvpp2_pool_refill(port, bm,
+ mvpp2_rxdesc_phys_addr_get(port, rx_desc),
+ mvpp2_rxdesc_virt_addr_get(port, rx_desc));
}
mvpp2_rxq_status_update(port, rxq->id, rx_received, rx_received);
}
@@ -4972,20 +5049,21 @@ static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
static void mvpp2_rx_error(struct mvpp2_port *port,
struct mvpp2_rx_desc *rx_desc)
{
- u32 status = rx_desc->status;
+ u32 status = mvpp2_rxdesc_status_get(port, rx_desc);
+ size_t sz = mvpp2_rxdesc_size_get(port, rx_desc);
switch (status & MVPP2_RXD_ERR_CODE_MASK) {
case MVPP2_RXD_ERR_CRC:
- netdev_err(port->dev, "bad rx status %08x (crc error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (crc error), size=%zu\n",
+ status, sz);
break;
case MVPP2_RXD_ERR_OVERRUN:
- netdev_err(port->dev, "bad rx status %08x (overrun error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (overrun error), size=%zu\n",
+ status, sz);
break;
case MVPP2_RXD_ERR_RESOURCE:
- netdev_err(port->dev, "bad rx status %08x (resource error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (resource error), size=%zu\n",
+ status, sz);
break;
}
}
@@ -5061,7 +5139,7 @@ static void mvpp2_buff_hdr_rx(struct mvpp2_port *port,
{
struct mvpp2_buff_hdr *buff_hdr;
struct sk_buff *skb;
- u32 rx_status = rx_desc->status;
+ u32 rx_status = mvpp2_rxdesc_status_get(port, rx_desc);
dma_addr_t buff_phys_addr;
unsigned long buff_virt_addr;
dma_addr_t buff_phys_addr_next;
@@ -5071,8 +5149,8 @@ static void mvpp2_buff_hdr_rx(struct mvpp2_port *port,
pool_id = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
MVPP2_RXD_BM_POOL_ID_OFFS;
- buff_phys_addr = rx_desc->buf_phys_addr;
- buff_virt_addr = rx_desc->buf_cookie;
+ buff_phys_addr = mvpp2_rxdesc_phys_addr_get(port, rx_desc);
+ buff_virt_addr = mvpp2_rxdesc_virt_addr_get(port, rx_desc);
do {
skb = (struct sk_buff *)buff_virt_addr;
@@ -5119,12 +5197,13 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
void *data;
rx_done++;
- rx_status = rx_desc->status;
- rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
- phys_addr = rx_desc->buf_phys_addr;
- data = (void *)rx_desc->buf_cookie;
+ rx_status = mvpp2_rxdesc_status_get(port, rx_desc);
+ rx_bytes = mvpp2_rxdesc_size_get(port, rx_desc);
+ rx_bytes -= MVPP2_MH_SIZE;
+ phys_addr = mvpp2_rxdesc_phys_addr_get(port, rx_desc);
+ data = (void *)mvpp2_rxdesc_virt_addr_get(port, rx_desc);
- bm = mvpp2_bm_cookie_build(rx_desc);
+ bm = mvpp2_bm_cookie_build(port, rx_desc);
pool = mvpp2_bm_cookie_pool_get(bm);
bm_pool = &port->priv->bm_pools[pool];
/* Check if buffer header is used */
@@ -5143,9 +5222,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
-
- mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
- rx_desc->buf_cookie);
+ mvpp2_pool_refill(port, bm, phys_addr,
+ (unsigned long)data);
continue;
}
@@ -5197,11 +5275,15 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
}
static inline void
-tx_desc_unmap_put(struct device *dev, struct mvpp2_tx_queue *txq,
+tx_desc_unmap_put(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
struct mvpp2_tx_desc *desc)
{
- dma_unmap_single(dev, desc->buf_phys_addr,
- desc->data_size, DMA_TO_DEVICE);
+ dma_addr_t buf_phys_addr =
+ mvpp2_txdesc_phys_addr_get(port, desc);
+ size_t buf_sz =
+ mvpp2_txdesc_size_get(port, desc);
+ dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
+ buf_sz, DMA_TO_DEVICE);
mvpp2_txq_desc_put(txq);
}
@@ -5220,28 +5302,31 @@ static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
void *addr = page_address(frag->page.p) + frag->page_offset;
tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
- tx_desc->phys_txq = txq->id;
- tx_desc->data_size = frag->size;
+ mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
+ mvpp2_txdesc_size_set(port, tx_desc, frag->size);
buf_phys_addr = dma_map_single(port->dev->dev.parent, addr,
- tx_desc->data_size,
+ frag->size,
DMA_TO_DEVICE);
if (dma_mapping_error(port->dev->dev.parent, buf_phys_addr)) {
mvpp2_txq_desc_put(txq);
goto error;
}
- tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
- tx_desc->buf_phys_addr = buf_phys_addr & (~MVPP2_TX_DESC_ALIGN);
+ mvpp2_txdesc_phys_addr_set(port, tx_desc,
+ buf_phys_addr & MVPP2_TX_DESC_ALIGN);
+ mvpp2_txdesc_offset_set(port, tx_desc,
+ buf_phys_addr & (~MVPP2_TX_DESC_ALIGN));
if (i == (skb_shinfo(skb)->nr_frags - 1)) {
/* Last descriptor */
- tx_desc->command = MVPP2_TXD_L_DESC;
- mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
+ mvpp2_txdesc_cmd_set(port, tx_desc,
+ MVPP2_TXD_L_DESC);
+ mvpp2_txq_inc_put(port, txq_pcpu, skb, tx_desc);
} else {
/* Descriptor in the middle: Not First, Not Last */
- tx_desc->command = 0;
- mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
+ mvpp2_txdesc_cmd_set(port, tx_desc, 0);
+ mvpp2_txq_inc_put(port, txq_pcpu, NULL, tx_desc);
}
}
@@ -5253,7 +5338,7 @@ static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
*/
for (i = i - 1; i >= 0; i--) {
tx_desc = txq->descs + i;
- tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+ tx_desc_unmap_put(port, txq, tx_desc);
}
return -ENOMEM;
@@ -5288,35 +5373,37 @@ static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
/* Get a descriptor for the first part of the packet */
tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
- tx_desc->phys_txq = txq->id;
- tx_desc->data_size = skb_headlen(skb);
+ mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
+ mvpp2_txdesc_size_set(port, tx_desc, skb_headlen(skb));
buf_phys_addr = dma_map_single(dev->dev.parent, skb->data,
- tx_desc->data_size, DMA_TO_DEVICE);
+ skb_headlen(skb), DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev->dev.parent, buf_phys_addr))) {
mvpp2_txq_desc_put(txq);
frags = 0;
goto out;
}
- tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
- tx_desc->buf_phys_addr = buf_phys_addr & ~MVPP2_TX_DESC_ALIGN;
+ mvpp2_txdesc_offset_set(port, tx_desc,
+ buf_phys_addr & MVPP2_TX_DESC_ALIGN);
+ mvpp2_txdesc_phys_addr_set(port, tx_desc,
+ buf_phys_addr & ~MVPP2_TX_DESC_ALIGN);
tx_cmd = mvpp2_skb_tx_csum(port, skb);
if (frags == 1) {
/* First and Last descriptor */
tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
- tx_desc->command = tx_cmd;
- mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
+ mvpp2_txdesc_cmd_set(port, tx_desc, tx_cmd);
+ mvpp2_txq_inc_put(port, txq_pcpu, skb, tx_desc);
} else {
/* First but not Last */
tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_PADDING_DISABLE;
- tx_desc->command = tx_cmd;
- mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
+ mvpp2_txdesc_cmd_set(port, tx_desc, tx_cmd);
+ mvpp2_txq_inc_put(port, txq_pcpu, NULL, tx_desc);
/* Continue with other skb fragments */
if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
- tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+ tx_desc_unmap_put(port, txq, tx_desc);
frags = 0;
goto out;
}
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCHv2 net-next 01/16] dt-bindings: net: update Marvell PPv2 binding for PPv2.2 support
From: Thomas Petazzoni @ 2016-12-28 16:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory Clement,
Nadav Haklai, Hanna Hawa, Yehuda Yitschak,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Stefan Chulski,
Marcin Wojtas, Thomas Petazzoni
In-Reply-To: <1482943592-12556-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Marvell PPv2 Device Tree binding was so far only used to describe
the PPv2.1 network controller, used in the Marvell Armada 375.
A new version of this IP block, PPv2.2 is used in the Marvell Armada
7K/8K processor. This commit extends the existing binding so that it can
also be used to describe PPv2.2 hardware.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
.../devicetree/bindings/net/marvell-pp2.txt | 66 ++++++++++++++++++----
1 file changed, 55 insertions(+), 11 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
index aa4f423..76071f3 100644
--- a/Documentation/devicetree/bindings/net/marvell-pp2.txt
+++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
@@ -1,17 +1,28 @@
-* Marvell Armada 375 Ethernet Controller (PPv2)
+* Marvell Armada 375 Ethernet Controller (PPv2.1)
+ Marvell Armada 7K/8K Ethernet Controller (PPv2.2)
Required properties:
-- compatible: should be "marvell,armada-375-pp2"
+- compatible: should be one of:
+ "marvell,armada-375-pp2"
+ "marvell,armada-7k-pp2"
- reg: addresses and length of the register sets for the device.
- Must contain the following register sets:
+ For "marvell,armada-375-pp2", must contain the following register
+ sets:
- common controller registers
- LMS registers
- In addition, at least one port register set is required.
-- clocks: a pointer to the reference clocks for this device, consequently:
- - main controller clock
- - GOP clock
-- clock-names: names of used clocks, must be "pp_clk" and "gop_clk".
+ - one register area per Ethernet port
+ For "marvell,armda-7k-pp2", must contain the following register
+ sets:
+ - common controller registers
+ - per-port registers
+
+- clocks: pointers to the reference clocks for this device, consequently:
+ - main controller clock (for both armada-375-pp2 and armada-7k-pp2)
+ - GOP clock (for both armada-375-pp2 and armada-7k-pp2)
+ - MG clock (only for armada-7k-pp2)
+- clock-names: names of used clocks, must be "pp_clk", "gop_clk" and
+ "mg_clk" (the latter only for armada-7k-pp2).
The ethernet ports are represented by subnodes. At least one port is
required.
@@ -19,8 +30,9 @@ required.
Required properties (port):
- interrupts: interrupt for the port
-- port-id: should be '0' or '1' for ethernet ports, and '2' for the
- loopback port
+- port-id: ID of the port from the MAC point of view
+- gop-port-id: only for marvell,armada-7k-pp2, ID of the port from the
+ GOP (Group Of Ports) point of view
- phy-mode: See ethernet.txt file in the same directory
Optional properties (port):
@@ -31,7 +43,7 @@ Optional properties (port):
then fixed link is assumed, and the 'fixed-link' property is
mandatory.
-Example:
+Example for marvell,armada-375-pp2:
ethernet@f0000 {
compatible = "marvell,armada-375-pp2";
@@ -59,3 +71,35 @@ ethernet@f0000 {
phy-mode = "gmii";
};
};
+
+Example for marvell,armada-7k-pp2:
+
+cpm_ethernet: ethernet@0 {
+ compatible = "marvell,armada-7k-pp22";
+ reg = <0x0 0x100000>,
+ <0x100000 0x80000>;
+ clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
+ clock-names = "pp_clk", "gop_clk", "gp_clk";
+ status = "disabled";
+
+ eth0: eth@0 {
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <0>;
+ gop-port-id = <0>;
+ status = "disabled";
+ };
+
+ eth1: eth@1 {
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <1>;
+ gop-port-id = <2>;
+ status = "disabled";
+ };
+
+ eth2: eth@2 {
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <2>;
+ gop-port-id = <3>;
+ status = "disabled";
+ };
+};
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH] net: wan: slic_ds26522: fix spelling mistake: "configurated" -> "configured"
From: Colin King @ 2016-12-28 16:44 UTC (permalink / raw)
To: David S . Miller, Javier Martinez Canillas, Zhao Qiang, netdev
Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
trivial fix to spelling mistake in pr_info message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wan/slic_ds26522.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wan/slic_ds26522.c b/drivers/net/wan/slic_ds26522.c
index b776a0a..9d9b4e0 100644
--- a/drivers/net/wan/slic_ds26522.c
+++ b/drivers/net/wan/slic_ds26522.c
@@ -218,7 +218,7 @@ static int slic_ds26522_probe(struct spi_device *spi)
ret = slic_ds26522_init_configure(spi);
if (ret == 0)
- pr_info("DS26522 cs%d configurated\n", spi->chip_select);
+ pr_info("DS26522 cs%d configured\n", spi->chip_select);
return ret;
}
--
2.10.2
^ permalink raw reply related
* [PATCH] net: atm: Fix warnings in net/atm/lec.c when !CONFIG_PROC_FS
From: Augusto Mecking Caringi @ 2016-12-28 16:02 UTC (permalink / raw)
To: netdev
Cc: Augusto Mecking Caringi, David S. Miller, Felipe Balbi, Kees Cook,
Mugunthan V N, Jarod Wilson, Javier Martinez Canillas,
Florian Westphal, linux-kernel
This patch fixes the following warnings when CONFIG_PROC_FS is not set:
linux/net/atm/lec.c: In function ‘lane_module_cleanup’:
linux/net/atm/lec.c:1062:27: error: ‘atm_proc_root’ undeclared (first
use in this function)
remove_proc_entry("lec", atm_proc_root);
^
linux/net/atm/lec.c:1062:27: note: each undeclared identifier is
reported only once for each function it appears in
Signed-off-by: Augusto Mecking Caringi <augustocaringi@gmail.com>
---
net/atm/lec.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 019557d..09cfe87 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1059,7 +1059,9 @@ static void __exit lane_module_cleanup(void)
{
int i;
+#ifdef CONFIG_PROC_FS
remove_proc_entry("lec", atm_proc_root);
+#endif
deregister_atm_ioctl(&lane_ioctl_ops);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net] net/sched: cls_flower: Fix missing addr_type in classify
From: Jiri Pirko @ 2016-12-28 15:48 UTC (permalink / raw)
To: Paul Blakey
Cc: David S. Miller, netdev, Jiri Pirko, Hadar Hen Zion, Or Gerlitz,
Roi Dayan
In-Reply-To: <1482929687-20159-1-git-send-email-paulb@mellanox.com>
Wed, Dec 28, 2016 at 01:54:47PM CET, paulb@mellanox.com wrote:
>Since we now use a non zero mask on addr_type, we are matching on its
>value (IPV4/IPV6). So before this fix, matching on enc_src_ip/enc_dst_ip
>failed in SW/classify path since its value was zero.
>This patch sets the proper value of addr_type for encapsulated packets.
>
>Fixes: 970bfcd09791 ('net/sched: cls_flower: Use mask for addr_type')
>Signed-off-by: Paul Blakey <paulb@mellanox.com>
>Reviewed-by: Hadar Hen Zion <hadarh@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
^ permalink raw reply
* [PATCH] ipv6: Should use consistent conditional judgement for ip6 fragment between __ip6_append_data and ip6_finish_output
From: Zheng Li @ 2016-12-28 15:23 UTC (permalink / raw)
To: linux-kernel, netdev, davem, kuznet, jmorris, yoshfuji, kaber; +Cc: james.z.li
From: Zheng Li <james.z.li@ericsson.com>
There is an inconsistent conditional judgement between __ip6_append_data
and ip6_finish_output functions, the variable length in __ip6_append_data
just include the length of application's payload and udp6 header, don't
include the length of ipv6 header, but in ip6_finish_output use
(skb->len > ip6_skb_dst_mtu(skb)) as judgement, and skb->len include the
length of ipv6 header.
That causes some particular application's udp6 payloads whose length are
between (MTU - IPv6 Header) and MTU were fragmented by ip6_fragment even
though the rst->dev support UFO feature.
Add the length of ipv6 header to length in __ip6_append_data to keep
consistent conditional judgement as ip6_finish_output for ip6 fragment.
Signed-off-by: Zheng Li <james.z.li@ericsson.com>
---
net/ipv6/ip6_output.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 70d0de40..38122d0 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1373,7 +1373,7 @@ static int __ip6_append_data(struct sock *sk,
*/
cork->length += length;
- if (((length > mtu) ||
+ if ((((length + fragheaderlen) > mtu) ||
(skb && skb_is_gso(skb))) &&
(sk->sk_protocol == IPPROTO_UDP) &&
(rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
--
2.7.4
^ permalink raw reply related
* [PATCH] net: avoid put_cmsg() possible copy longer data than input
From: yuan linyu @ 2016-12-28 14:34 UTC (permalink / raw)
To: netdev; +Cc: David S . Miller, yuan linyu
From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
if CMSG_ALIGN(sizeof(struct cmsghdr)) > sizeof(struct cmsghdr),
original (cmlen - sizeof(struct cmsghdr)) may greater than
input len.
---
include/linux/socket.h | 12 ++++++------
net/compat.c | 28 +++++++++++++++-------------
net/core/scm.c | 10 +++++-----
net/ipv4/ip_sockglue.c | 2 +-
net/rxrpc/sendmsg.c | 2 +-
net/socket.c | 3 +--
6 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index b5cc5a6..72b61d8 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -78,8 +78,8 @@ struct mmsghdr {
struct cmsghdr {
__kernel_size_t cmsg_len; /* data byte count, including hdr */
- int cmsg_level; /* originating protocol */
- int cmsg_type; /* protocol-specific type */
+ int cmsg_level; /* originating protocol */
+ int cmsg_type; /* protocol-specific type */
};
/*
@@ -91,10 +91,10 @@ struct cmsghdr {
#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
-
-#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
-#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
-#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
+#define CMSG_ALIGN_HDR_LEN CMSG_ALIGN(sizeof(struct cmsghdr))
+#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN_HDR_LEN))
+#define CMSG_SPACE(len) (CMSG_ALIGN_HDR_LEN + CMSG_ALIGN(len))
+#define CMSG_LEN(len) (CMSG_ALIGN_HDR_LEN + (len))
#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ? \
(struct cmsghdr *)(ctl) : \
diff --git a/net/compat.c b/net/compat.c
index 96c544b..b291ff4 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -88,13 +88,13 @@ int get_compat_msghdr(struct msghdr *kmsg,
/* Bleech... */
#define CMSG_COMPAT_ALIGN(len) ALIGN((len), sizeof(s32))
-
+#define CMSG_COMPAT_ALIGN_HDR_LEN CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))
#define CMSG_COMPAT_DATA(cmsg) \
- ((void __user *)((char __user *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
+ ((void __user *)((char __user *)(cmsg) + CMSG_COMPAT_ALIGN_HDR_LEN))
#define CMSG_COMPAT_SPACE(len) \
- (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
+ (CMSG_COMPAT_ALIGN_HDR_LEN + CMSG_COMPAT_ALIGN(len))
#define CMSG_COMPAT_LEN(len) \
- (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
+ (CMSG_COMPAT_ALIGN_HDR_LEN + (len))
#define CMSG_COMPAT_FIRSTHDR(msg) \
(((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \
@@ -141,9 +141,8 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
return -EINVAL;
- tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- tmp = CMSG_ALIGN(tmp);
+ tmp = (ucmlen - CMSG_COMPAT_ALIGN_HDR_LEN);
+ tmp = CMSG_SPACE(tmp);
kcmlen += tmp;
ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
}
@@ -168,9 +167,8 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
goto Efault;
if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
goto Einval;
- tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
+ tmp = (ucmlen - CMSG_COMPAT_ALIGN_HDR_LEN);
+ if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_SPACE(tmp))
goto Einval;
kcmsg->cmsg_len = tmp;
tmp = CMSG_ALIGN(tmp);
@@ -178,7 +176,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
copy_from_user(CMSG_DATA(kcmsg),
CMSG_COMPAT_DATA(ucmsg),
- (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
+ (ucmlen - CMSG_COMPAT_ALIGN_HDR_LEN)))
goto Efault;
/* Advance. */
@@ -245,7 +243,8 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
return -EFAULT;
- if (copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
+ if (cmlen > CMSG_COMPAT_ALIGN_HDR_LEN &&
+ copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - CMSG_COMPAT_ALIGN_HDR_LEN))
return -EFAULT;
cmlen = CMSG_COMPAT_SPACE(len);
if (kmsg->msg_controllen < cmlen)
@@ -258,12 +257,15 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
{
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
- int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int);
+ int fdmax = 0;
int fdnum = scm->fp->count;
struct file **fp = scm->fp->fp;
int __user *cmfptr;
int err = 0, i;
+ if (kmsg->msg_controllen > CMSG_COMPAT_ALIGN_HDR_LEN)
+ fdmax = (kmsg->msg_controllen - CMSG_COMPAT_ALIGN_HDR_LEN) / sizeof(int);
+
if (fdnum < fdmax)
fdmax = fdnum;
diff --git a/net/core/scm.c b/net/core/scm.c
index d882043..262c4cf 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -223,7 +223,7 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
if (MSG_CMSG_COMPAT & msg->msg_flags)
return put_cmsg_compat(msg, level, type, len, data);
- if (cm==NULL || msg->msg_controllen < sizeof(*cm)) {
+ if (cm == NULL || msg->msg_controllen < sizeof(*cm)) {
msg->msg_flags |= MSG_CTRUNC;
return 0; /* XXX: return error? check spec. */
}
@@ -238,7 +238,8 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
err = -EFAULT;
if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
goto out;
- if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
+ if (cmlen > CMSG_ALIGN_HDR_LEN &&
+ copy_to_user(CMSG_DATA(cm), data, cmlen - CMSG_ALIGN_HDR_LEN))
goto out;
cmlen = CMSG_SPACE(len);
if (msg->msg_controllen < cmlen)
@@ -267,9 +268,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
return;
}
- if (msg->msg_controllen > sizeof(struct cmsghdr))
- fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
- / sizeof(int));
+ if (msg->msg_controllen > CMSG_ALIGN_HDR_LEN)
+ fdmax = ((msg->msg_controllen - CMSG_ALIGN_HDR_LEN) / sizeof(int));
if (fdnum < fdmax)
fdmax = fdnum;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 57e1405..a9d00db 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -272,7 +272,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
continue;
switch (cmsg->cmsg_type) {
case IP_RETOPTS:
- err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+ err = cmsg->cmsg_len - CMSG_ALIGN_HDR_LEN;
/* Our caller is responsible for freeing ipc->opt */
err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg),
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index b214a4d..acf4ca5 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -376,7 +376,7 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
if (!CMSG_OK(msg, cmsg))
return -EINVAL;
- len = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+ len = cmsg->cmsg_len - CMSG_ALIGN_HDR_LEN;
_debug("CMSG %d, %d, %d",
cmsg->cmsg_level, cmsg->cmsg_type, len);
diff --git a/net/socket.c b/net/socket.c
index 8487bf1..17f05ab 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1917,8 +1917,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
(struct compat_msghdr __user *)msg;
struct sockaddr_storage address;
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
- unsigned char ctl[sizeof(struct cmsghdr) + 20]
- __aligned(sizeof(__kernel_size_t));
+ unsigned char ctl[CMSG_LEN(20)] __aligned(sizeof(__kernel_size_t));
/* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl;
int ctl_len;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 01/12] Make and configuration files.
From: Joe Perches @ 2016-12-28 14:34 UTC (permalink / raw)
To: David VomLehn, netdev
Cc: Simon Edelhaus, Dmitrii Tarakanov, Alexander Loktionov
In-Reply-To: <9cc1565a3a398b4f70248ca98d12991071142682.1482844668.git.vomlehn@texas.net>
On Tue, 2016-12-27 at 05:17 -0800, David VomLehn wrote:
> Patches to create the make and configuration file
[]
> \ No newline at end of file
Not good
> diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile
A really atypical Makefile you'll probably need to rework
^ permalink raw reply
* Admin
From: administrador @ 2016-12-28 13:23 UTC (permalink / raw)
To: Recipients
ATENCIÓN;
Su buzón ha superado el límite de almacenamiento, que es de 5 GB definidos por el administrador, quien actualmente está ejecutando en 10.9GB, no puede ser capaz de enviar o recibir correo nuevo hasta que vuelva a validar su buzón de correo electrónico. Para revalidar su buzón de correo, envíe la siguiente información a continuación:
nombre:
Nombre de usuario:
contraseña:
Confirmar contraseña:
E-mail:
teléfono:
Si usted no puede revalidar su buzón, el buzón se deshabilitará!
Disculpa las molestias.
Código de verificación: es:00916gbd51.16
Correo Soporte Técnico © 2016
¡gracias
Sistemas administrador
^ permalink raw reply
* RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
From: Rafal Ozieblo @ 2016-12-28 13:23 UTC (permalink / raw)
To: Andrei Pistirica, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, davem@davemloft.net,
nicolas.ferre@atmel.com, harinikatakamlinux@gmail.com,
harini.katakam@xilinx.com
Cc: boris.brezillon@free-electrons.com,
alexandre.belloni@free-electrons.com, michals@xilinx.com,
tbultel@pixelsurmer.com, anirudh@xilinx.com, punnaia@xilinx.com,
richardcochran@gmail.com
In-Reply-To: <1481720175-12703-1-git-send-email-andrei.pistirica@microchip.com>
> From: Andrei Pistirica [mailto:andrei.pistirica@microchip.com]
> Sent: 14 grudnia 2016 13:56
> Subject: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
>
> Cadence GEM provides a 102 bit time counter with 48 bits for seconds,
> 30 bits for nsecs and 24 bits for sub-nsecs to control 1588 timestamping.
>
> This patch does the following:
> - Registers to ptp clock framework
> - Timer initialization is done by writing time of day to the timer counter.
> - ns increment register is programmed as NSEC_PER_SEC/tsu-clock-rate.
> For a 16 bit subns precision, the subns increment equals
> remainder of (NS_PER_SEC/TSU_CLK) * (2^16).
> - Timestamps are obtained from the TX/RX PTP event/PEER registers.
> The timestamp obtained thus is updated in skb for upper layers to access.
> - The drivers register functions with ptp to perform time and frequency
> adjustment.
> - Time adjustment is done by writing to the 1558_ADJUST register.
> The controller will read the delta in this register and update the timer
> counter register. Alternatively, for large time offset adjustments,
> the driver reads the secs and nsecs counter values, adds/subtracts the
> delta and updates the timer counter.
> - Frequency is adjusted by adjusting addend (8bit nanosecond increment) and
> addendsub (16bit increment nanosecond fractions).
> The 102bit counter is incremented at nominal frequency with addend and
> addendsub values. Each period addend and addendsub values are adjusted
> based on ppm drift.
>
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Harini Katakam <harinik@xilinx.com>
> ---
> Patch history:
>
> Version 1:
> This patch is based on original Harini's patch, implemented in a separate file to ease the review/maintanance and integration with other platforms (e.g. Zynq Ultrascale+ MPSoC).
> Feature was tested on SAMA5D2 platform using ptp4l v1.6 from linuxptp project and also with ptpd2 version 2.3.1. PTP was tested over
> IPv4,IPv6 and 802.3 protocols.
>
> In case that macb is compiled as a module, it has been renamed to cadence-macb.ko to avoid naming confusion in Makefile.
>
> Version 2 modifications:
> - bitfields for TSU are named according to SAMA5D2 data sheet
> - identify GEM-PTP support based on platform capability
> - add spinlock for TSU access
> - change macb_ptp_adjfreq and use fewer 64bit divisions
>
> Version 3 modifications:
> - new adjfine api with one 64 division for frequency adjustment
> (based on Richard's input)
> - add maximum adjustment frequency (ppb) based on nominal frequency
> - per platform PTP configuration
> - cosmetic changes
> Note 1: Kbuild uses "select" instead of "imply", and the macb maintainer agreed
> to make the change when it will be available in net-next.
>
> Version 4 modifications:
> - update adjfine for a better approximation
> - add maximum adjustment frequency callback to PTP platform configuraion
>
> Note 1: This driver does not support GEM-GXL!
> Note 2: Patch on net-next, on December 14th.
>
> drivers/net/ethernet/cadence/Kconfig | 10 +-
> drivers/net/ethernet/cadence/Makefile | 8 +-
> drivers/net/ethernet/cadence/macb.h | 118 ++++++++++
> drivers/net/ethernet/cadence/macb_ptp.c | 366 ++++++++++++++++++++++++++++++++
> 4 files changed, 500 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/cadence/macb_ptp.c
>
> diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
> index f0bcb15..ebbc65f 100644
> --- a/drivers/net/ethernet/cadence/Kconfig
> +++ b/drivers/net/ethernet/cadence/Kconfig
> @@ -29,6 +29,14 @@ config MACB
> support for the MACB/GEM chip.
>
> To compile this driver as a module, choose M here: the module
> - will be called macb.
> + will be called cadence-macb.
> +
> +config MACB_USE_HWSTAMP
> + bool "Use IEEE 1588 hwstamp"
> + depends on MACB
> + default y
> + select PTP_1588_CLOCK
> + ---help---
> + Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
>
> endif # NET_CADENCE
> diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
> index 91f79b1..4402d42 100644
> --- a/drivers/net/ethernet/cadence/Makefile
> +++ b/drivers/net/ethernet/cadence/Makefile
> @@ -2,4 +2,10 @@
> # Makefile for the Atmel network device drivers.
> #
>
> -obj-$(CONFIG_MACB) += macb.o
> +cadence-macb-y := macb.o
> +
> +ifeq ($(CONFIG_MACB_USE_HWSTAMP),y)
> +cadence-macb-y += macb_ptp.o
> +endif
> +
> +obj-$(CONFIG_MACB) += cadence-macb.o
> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
> index d67adad..e65e985 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -10,6 +10,9 @@
> #ifndef _MACB_H
> #define _MACB_H
>
> +#include <linux/ptp_clock.h>
> +#include <linux/ptp_clock_kernel.h>
> +
> #define MACB_GREGS_NBR 16
> #define MACB_GREGS_VERSION 2
> #define MACB_MAX_QUEUES 8
> @@ -131,6 +134,20 @@
> #define GEM_RXIPCCNT 0x01a8 /* IP header Checksum Error Counter */
> #define GEM_RXTCPCCNT 0x01ac /* TCP Checksum Error Counter */
> #define GEM_RXUDPCCNT 0x01b0 /* UDP Checksum Error Counter */
> +#define GEM_TISUBN 0x01bc /* 1588 Timer Increment Sub-ns */
> +#define GEM_TSH 0x01c0 /* 1588 Timer Seconds High */
> +#define GEM_TSL 0x01d0 /* 1588 Timer Seconds Low */
> +#define GEM_TN 0x01d4 /* 1588 Timer Nanoseconds */
> +#define GEM_TA 0x01d8 /* 1588 Timer Adjust */
> +#define GEM_TI 0x01dc /* 1588 Timer Increment */
> +#define GEM_EFTSL 0x01e0 /* PTP Event Frame Tx Seconds Low */
> +#define GEM_EFTN 0x01e4 /* PTP Event Frame Tx Nanoseconds */
> +#define GEM_EFRSL 0x01e8 /* PTP Event Frame Rx Seconds Low */
> +#define GEM_EFRN 0x01ec /* PTP Event Frame Rx Nanoseconds */
> +#define GEM_PEFTSL 0x01f0 /* PTP Peer Event Frame Tx Secs Low */
> +#define GEM_PEFTN 0x01f4 /* PTP Peer Event Frame Tx Ns */
> +#define GEM_PEFRSL 0x01f8 /* PTP Peer Event Frame Rx Sec Low */
> +#define GEM_PEFRN 0x01fc /* PTP Peer Event Frame Rx Ns */
> #define GEM_DCFG1 0x0280 /* Design Config 1 */
> #define GEM_DCFG2 0x0284 /* Design Config 2 */
> #define GEM_DCFG3 0x0288 /* Design Config 3 */
> @@ -174,6 +191,7 @@
> #define MACB_NCR_TPF_SIZE 1
> #define MACB_TZQ_OFFSET 12 /* Transmit zero quantum pause frame */
> #define MACB_TZQ_SIZE 1
> +#define MACB_SRTSM_OFFSET 15
>
> /* Bitfields in NCFGR */
> #define MACB_SPD_OFFSET 0 /* Speed */
> @@ -319,6 +337,32 @@
> #define MACB_PTZ_SIZE 1
> #define MACB_WOL_OFFSET 14 /* Enable wake-on-lan interrupt */
> #define MACB_WOL_SIZE 1
> +#define MACB_DRQFR_OFFSET 18 /* PTP Delay Request Frame Received */
> +#define MACB_DRQFR_SIZE 1
> +#define MACB_SFR_OFFSET 19 /* PTP Sync Frame Received */
> +#define MACB_SFR_SIZE 1
> +#define MACB_DRQFT_OFFSET 20 /* PTP Delay Request Frame Transmitted */
> +#define MACB_DRQFT_SIZE 1
> +#define MACB_SFT_OFFSET 21 /* PTP Sync Frame Transmitted */
> +#define MACB_SFT_SIZE 1
> +#define MACB_PDRQFR_OFFSET 22 /* PDelay Request Frame Received */
> +#define MACB_PDRQFR_SIZE 1
> +#define MACB_PDRSFR_OFFSET 23 /* PDelay Response Frame Received */
> +#define MACB_PDRSFR_SIZE 1
> +#define MACB_PDRQFT_OFFSET 24 /* PDelay Request Frame Transmitted */
> +#define MACB_PDRQFT_SIZE 1
> +#define MACB_PDRSFT_OFFSET 25 /* PDelay Response Frame Transmitted */
> +#define MACB_PDRSFT_SIZE 1
> +#define MACB_SRI_OFFSET 26 /* TSU Seconds Register Increment */
> +#define MACB_SRI_SIZE 1
> +
> +/* Timer increment fields */
> +#define MACB_TI_CNS_OFFSET 0
> +#define MACB_TI_CNS_SIZE 8
> +#define MACB_TI_ACNS_OFFSET 8
> +#define MACB_TI_ACNS_SIZE 8
> +#define MACB_TI_NIT_OFFSET 16
> +#define MACB_TI_NIT_SIZE 8
>
> /* Bitfields in MAN */
> #define MACB_DATA_OFFSET 0 /* data */
> @@ -386,6 +430,17 @@
> #define GEM_PBUF_LSO_OFFSET 27
> #define GEM_PBUF_LSO_SIZE 1
>
> +/* Bitfields in TISUBN */
> +#define GEM_SUBNSINCR_OFFSET 0
> +#define GEM_SUBNSINCR_SIZE 16
> +
> +/* Bitfields in TI */
> +#define GEM_NSINCR_OFFSET 0
> +#define GEM_NSINCR_SIZE 8
> +
> +/* Bitfields in ADJ */
> +#define GEM_ADDSUB_OFFSET 31
> +#define GEM_ADDSUB_SIZE 1
> /* Constants for CLK */
> #define MACB_CLK_DIV8 0
> #define MACB_CLK_DIV16 1
> @@ -417,6 +472,7 @@
> #define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
> #define MACB_CAPS_SG_DISABLED 0x40000000
> #define MACB_CAPS_MACB_IS_GEM 0x80000000
> +#define MACB_CAPS_GEM_HAS_PTP 0x00000020
>
> /* LSO settings */
> #define MACB_LSO_UFO_ENABLE 0x01
> @@ -782,6 +838,20 @@ struct macb_or_gem_ops {
> int (*mog_rx)(struct macb *bp, int budget);
> };
>
> +/* MACB-PTP interface: adapt to platform needs and GEM (e.g. GXL). */
> +struct macb_ptp_info {
> + void (*ptp_init)(struct net_device *ndev);
> + void (*ptp_remove)(struct net_device *ndev);
> + s32 (*get_ptp_max_adj)(void);
> + unsigned int (*get_tsu_rate)(struct macb *bp);
> + int (*get_ts_info)(struct net_device *dev,
> + struct ethtool_ts_info *info);
> + int (*get_hwtst)(struct net_device *netdev,
> + struct ifreq *ifr);
> + int (*set_hwtst)(struct net_device *netdev,
> + struct ifreq *ifr, int cmd);
> +};
> +
> struct macb_config {
> u32 caps;
> unsigned int dma_burst_length;
> @@ -874,11 +944,59 @@ struct macb {
> unsigned int jumbo_max_len;
>
> u32 wol;
> +
> + struct macb_ptp_info *ptp_info;
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> + bool hwts_tx_en;
> + bool hwts_rx_en;
> + spinlock_t tsu_clk_lock; /* gem tsu clock locking */
> + unsigned int tsu_rate;
> +
> + struct ptp_clock *ptp_clock;
> + struct ptp_clock_info ptp_caps;
> + u32 ns_incr;
> + u32 subns_incr;
> +#endif
> };
>
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> +void gem_ptp_init(struct net_device *ndev); void gem_ptp_remove(struct
> +net_device *ndev); void gem_ptp_txstamp(struct macb *bp, struct sk_buff
> +*skb); void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb);
> +
> +static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff
> +*skb) {
> + if (!bp->hwts_tx_en)
> + return;
> +
> + return gem_ptp_txstamp(bp, skb);
> +}
> +
> +static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff
> +*skb) {
> + if (!bp->hwts_rx_en)
> + return;
> +
> + return gem_ptp_rxstamp(bp, skb);
> +}
> +
> +#else
> +static inline void gem_ptp_init(struct net_device *ndev) { } static
> +inline void gem_ptp_remove(struct net_device *ndev) { }
> +
> +static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff
> +*skb) { } static inline void gem_ptp_do_rxstamp(struct macb *bp, struct
> +sk_buff *skb) { } #endif
> +
> static inline bool macb_is_gem(struct macb *bp) {
> return !!(bp->caps & MACB_CAPS_MACB_IS_GEM); }
>
> +static inline bool gem_has_ptp(struct macb *bp) {
> + return !!(bp->caps & MACB_CAPS_GEM_HAS_PTP); }
> +
> #endif /* _MACB_H */
> diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
> new file mode 100644
> index 0000000..6121b2a
> --- /dev/null
> +++ b/drivers/net/ethernet/cadence/macb_ptp.c
> @@ -0,0 +1,366 @@
> +/*
> + * 1588 PTP support for GEM device.
> + *
> + * Copyright (C) 2016 Microchip Technology
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/etherdevice.h>
> +#include <linux/platform_device.h>
> +#include <linux/time64.h>
> +#include <linux/ptp_classify.h>
> +#include <linux/if_ether.h>
> +#include <linux/if_vlan.h>
> +#include <linux/net_tstamp.h>
> +
> +#include "macb.h"
> +
> +#define GEM_PTP_TIMER_NAME "gem-ptp-timer"
> +
> +static inline void gem_tsu_get_time(struct macb *bp,
> + struct timespec64 *ts)
> +{
> + u64 sec, sech, secl;
> +
> + spin_lock(&bp->tsu_clk_lock);
> +
> + /* GEM's internal time */
> + sech = gem_readl(bp, TSH);
> + secl = gem_readl(bp, TSL);
> + ts->tv_nsec = gem_readl(bp, TN);
> + ts->tv_sec = (sech << 32) | secl;
> +
> + /* minimize error */
> + sech = gem_readl(bp, TSH);
> + secl = gem_readl(bp, TSL);
> + sec = (sech << 32) | secl;
> + if (ts->tv_sec != sec) {
> + ts->tv_sec = sec;
> + ts->tv_nsec = gem_readl(bp, TN);
> + }
> +
> + spin_unlock(&bp->tsu_clk_lock);
> +}
> +
> +static inline void gem_tsu_set_time(struct macb *bp,
> + const struct timespec64 *ts)
> +{
> + u32 ns, sech, secl;
> + s64 word_mask = 0xffffffff;
> +
> + sech = (u32)ts->tv_sec;
> + secl = (u32)ts->tv_sec;
> + ns = ts->tv_nsec;
> + if (ts->tv_sec > word_mask)
> + sech = (ts->tv_sec >> 32);
> +
> + spin_lock(&bp->tsu_clk_lock);
> +
> + /* TSH doesn't latch the time and no atomicity! */
> + gem_writel(bp, TN, 0); /* clear to avoid overflow */
> + gem_writel(bp, TSH, sech);
> + gem_writel(bp, TSL, secl);
> + gem_writel(bp, TN, ns);
> +
> + spin_unlock(&bp->tsu_clk_lock);
> +}
> +
> +static int gem_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
> +{
> + struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> + u32 word, diff;
> + u64 adj, rate;
> + int neg_adj = 0;
> +
> + if (scaled_ppm < 0) {
> + neg_adj = 1;
> + scaled_ppm = -scaled_ppm;
> + }
> + rate = scaled_ppm;
> +
> + /* word: unused(8bit) | ns(8bit) | fractions(16bit) */
> + word = (bp->ns_incr << 16) + bp->subns_incr;
> +
> + adj = word;
> + adj *= rate;
> + adj += 500000UL << 16;
> + adj >>= 16; /* remove fractions */
> + diff = div_u64(adj, 1000000UL);
> + word = neg_adj ? word - diff : word + diff;
> +
> + spin_lock(&bp->tsu_clk_lock);
> +
> + gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, (word & 0xffff)));
> + gem_writel(bp, TI, GEM_BF(NSINCR, (word >> 16)));
> +
> + spin_unlock(&bp->tsu_clk_lock);
> + return 0;
> +}
> +
> +static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) {
> + struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> + struct timespec64 now, then = ns_to_timespec64(delta);
> + u32 adj, sign = 0;
> +
> + if (delta < 0) {
> + delta = -delta;
> + sign = 1;
> + }
> +
> + if (delta > 0x3FFFFFFF) {
> + gem_tsu_get_time(bp, &now);
> +
> + if (sign)
> + now = timespec64_sub(now, then);
> + else
> + now = timespec64_add(now, then);
> +
> + gem_tsu_set_time(bp, (const struct timespec64 *)&now);
> + } else {
> + adj = delta;
> + if (sign)
> + adj |= GEM_BIT(ADDSUB);
> +
> + gem_writel(bp, TA, adj);
> + }
> +
> + return 0;
> +}
> +
> +static int gem_ptp_gettime(struct ptp_clock_info *ptp, struct
> +timespec64 *ts) {
> + struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +
> + gem_tsu_get_time(bp, ts);
> +
> + return 0;
> +}
> +
> +static int gem_ptp_settime(struct ptp_clock_info *ptp,
> + const struct timespec64 *ts)
> +{
> + struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +
> + gem_tsu_set_time(bp, ts);
> +
> + return 0;
> +}
> +
> +static int gem_ptp_enable(struct ptp_clock_info *ptp,
> + struct ptp_clock_request *rq, int on) {
> + return -EOPNOTSUPP;
> +}
I think, we can support here:
1. PTP_CLK_REQ_EXTTS (interrupt mask register 0x030, bit 29: tsu_timer_comparison_mask)
2. PTP_CLK_REQ_PPS (interrupt mask register 0x030, bit 26: tsu_seconds_register_increment_mask)
> +
> +static struct ptp_clock_info gem_ptp_caps_template = {
> + .owner = THIS_MODULE,
> + .name = GEM_PTP_TIMER_NAME,
> + .max_adj = 0,
> + .n_alarm = 0,
> + .n_ext_ts = 0,
> + .n_per_out = 0,
> + .n_pins = 0,
> + .pps = 0,
> + .adjfine = gem_ptp_adjfine,
> + .adjtime = gem_ptp_adjtime,
> + .gettime64 = gem_ptp_gettime,
> + .settime64 = gem_ptp_settime,
> + .enable = gem_ptp_enable,
> +};
> +
> +static void gem_ptp_init_timer(struct macb *bp) {
> + struct timespec64 now;
> + u32 rem = 0;
> +
> + getnstimeofday64(&now);
> + gem_tsu_set_time(bp, (const struct timespec64 *)&now);
Why do you change TSU clock here? Is it necessary? You overwrite all values
even when someone doesn't need it. ptp4l calls ioctl SIOCSHWTSTAMP on start.
IMHO, there should be set up TSU and Increments.
> +
> + bp->ns_incr = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
> + if (rem) {
> + u64 adj = rem;
> +
> + adj <<= 16; /* 16 bits nsec fragments */
> + bp->subns_incr = div_u64(adj, bp->tsu_rate);
> + } else {
> + bp->subns_incr = 0;
> + }
> +
> + gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, bp->subns_incr));
> + gem_writel(bp, TI, GEM_BF(NSINCR, bp->ns_incr));
The same comment like above.
> + gem_writel(bp, TA, 0);
What is the reason for zeroing Timer Adjust Register?
> +}
> +
> +static void gem_ptp_clear_timer(struct macb *bp) {
> + bp->ns_incr = 0;
> + bp->subns_incr = 0;
> +
> + gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, 0));
> + gem_writel(bp, TI, GEM_BF(NSINCR, 0));
> + gem_writel(bp, TA, 0);
> +}
> +
> +/* While GEM can timestamp PTP packets, it does not mark the RX
> +descriptor
> + * to identify them. UDP packets must be parsed to identify PTP packets.
> + *
> + * Note: Inspired from drivers/net/ethernet/ti/cpts.c */ static int
> +gem_get_ptp_peer(struct sk_buff *skb, int ptp_class) {
> + unsigned int offset = 0;
> + u8 *msgtype, *data = skb->data;
> +
> + /* PTP frames are rare! */
> + if (likely(ptp_class == PTP_CLASS_NONE))
> + return -1;
> +
> + if (ptp_class & PTP_CLASS_VLAN)
> + offset += VLAN_HLEN;
> +
> + switch (ptp_class & PTP_CLASS_PMASK) {
> + case PTP_CLASS_IPV4:
> + offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
> + break;
> + case PTP_CLASS_IPV6:
> + offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
> + break;
> + case PTP_CLASS_L2:
> + offset += ETH_HLEN;
> + break;
> +
> + /* something went wrong! */
> + default:
> + return -1;
> + }
> +
> + if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID)
> + return -1;
> +
> + if (unlikely(ptp_class & PTP_CLASS_V1))
> + msgtype = data + offset + OFF_PTP_CONTROL;
> + else
> + msgtype = data + offset;
> +
> + return (*msgtype) & 0x2;
> +}
> +
> +static void gem_ptp_tx_hwtstamp(struct macb *bp, struct sk_buff *skb,
> + int peer_ev)
> +{
> + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
> + struct timespec64 ts;
> + u64 ns;
> +
> + /* PTP Peer Event Frame packets */
> + if (peer_ev) {
> + ts.tv_sec = gem_readl(bp, PEFTSL);
> + ts.tv_nsec = gem_readl(bp, PEFTN);
> +
> + /* PTP Event Frame packets */
> + } else {
> + ts.tv_sec = gem_readl(bp, EFTSL);
> + ts.tv_nsec = gem_readl(bp, EFTN);
> + }
I'm wondering what is a difference between timestamp in transmit buffer descriptor (Word 2 and 3)
and PTP Event Frame Transmitted Seconds/Nanoseconds Register (0x1E0, 0x1E4).
> + ns = timespec64_to_ns(&ts);
> +
> + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
> + shhwtstamps->hwtstamp = ns_to_ktime(ns);
> + skb_tstamp_tx(skb, skb_hwtstamps(skb)); }
> +
> +static void gem_ptp_rx_hwtstamp(struct macb *bp, struct sk_buff *skb,
> + int peer_ev)
> +{
> + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
> + struct timespec64 ts;
> + u64 ns;
> +
> + if (peer_ev) {
> + /* PTP Peer Event Frame packets */
> + ts.tv_sec = gem_readl(bp, PEFRSL);
> + ts.tv_nsec = gem_readl(bp, PEFRN);
> + } else {
> + /* PTP Event Frame packets */
> + ts.tv_sec = gem_readl(bp, EFRSL);
> + ts.tv_nsec = gem_readl(bp, EFRN);
> + }
The same concerns like above.
> + ns = timespec64_to_ns(&ts);
> +
> + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
> + shhwtstamps->hwtstamp = ns_to_ktime(ns); }
> +
> +/* no static, GEM PTP interface functions */ void
> +gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb) {
> + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
> + int class = ptp_classify_raw(skb);
> + int peer;
> +
> + peer = gem_get_ptp_peer(skb, class);
> + if (peer < 0)
> + return;
> +
> + /* Timestamp this packet */
> + gem_ptp_tx_hwtstamp(bp, skb, peer);
> + }
> +}
> +
> +void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb) {
> + int class, peer;
> +
> + __skb_push(skb, ETH_HLEN);
> + class = ptp_classify_raw(skb);
> + __skb_pull(skb, ETH_HLEN);
> +
> + peer = gem_get_ptp_peer(skb, class);
> + if (peer < 0)
> + return;
> +
> + gem_ptp_rx_hwtstamp(bp, skb, peer);
> +}
> +
> +void gem_ptp_init(struct net_device *ndev) {
> + struct macb *bp = netdev_priv(ndev);
> +
> + spin_lock_init(&bp->tsu_clk_lock);
> + bp->ptp_caps = gem_ptp_caps_template;
> +
> + /* nominal frequency and maximum adjustment in ppb */
> + bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
> + bp->ptp_caps.max_adj = bp->ptp_info->get_ptp_max_adj();
> +
> + gem_ptp_init_timer(bp);
> +
> + bp->ptp_clock = ptp_clock_register(&bp->ptp_caps, NULL);
> + if (IS_ERR(&bp->ptp_clock)) {
> + bp->ptp_clock = NULL;
> + pr_err("ptp clock register failed\n");
> + return;
But you have already overwritten TSU and Increments.
> + }
> +
> + dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
> + GEM_PTP_TIMER_NAME);
> +}
> +
> +void gem_ptp_remove(struct net_device *ndev) {
> + struct macb *bp = netdev_priv(ndev);
> +
> + if (bp->ptp_clock)
> + ptp_clock_unregister(bp->ptp_clock);
> +
> + gem_ptp_clear_timer(bp);
> +
> + dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
> + GEM_PTP_TIMER_NAME);
> +}
> --
> 2.7.4
>
Why don't you support HWTSTAMP_TX_ONESTEP_SYNC?
(Network control register 0x000, bit 24: one_step_sync_mode)
Best regards,
Rafal Ozieblo | Firmware System Engineer,
www.cadence.com
^ permalink raw reply
* [PATCH iproute2 net-next] tc: flower: support matching flags
From: Paul Blakey @ 2016-12-28 13:06 UTC (permalink / raw)
To: netdev, Stephen Hemminger
Cc: David S. Miller, Hadar Hen Zion, Or Gerlitz, Roi Dayan,
Paul Blakey
Enhance flower to support matching on flags.
The 1st flag allows to match on whether the packet is
an IP fragment.
Example:
# add a flower filter that will drop fragmented packets
# (bit 0 of control flags)
tc filter add dev ens4f0 protocol ip parent ffff: \
flower \
src_mac e4:1d:2d:fd:8b:01 \
dst_mac e4:1d:2d:fd:8b:02 \
indev ens4f0 \
matching_flags 0x1/0x1 \
action drop
Signed-off-by: Paul Blakey <paulb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
---
man/man8/tc-flower.8 | 11 +++++++++++
tc/f_flower.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
index 90fdfba..40117a9 100644
--- a/man/man8/tc-flower.8
+++ b/man/man8/tc-flower.8
@@ -39,6 +39,8 @@ flower \- flow based traffic control filter
.IR KEY-ID " | {"
.BR enc_dst_ip " | " enc_src_ip " } { "
.IR ipv4_address " | " ipv6_address " } | "
+.B matching_flags
+.IR MATCHING-FLAGS " }"
.SH DESCRIPTION
The
.B flower
@@ -134,6 +136,15 @@ Match on IP tunnel metadata. Key id
is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel).
.I ADDRESS
must be a valid IPv4 or IPv6 address.
+.TP
+.BI matching_flags " MATCHING-FLAGS"
+Match on various dissector flags.
+.I MATCHING-FLAGS
+may be specified with or without a mask:
+.BR FLAGS
+or
+.BR FLAGS/FLAGS_MASK
+where each arg is an unsigned 32bit value in hexadecimal format.
.SH NOTES
As stated above where applicable, matches of a certain layer implicitly depend
on the matches of the next lower layer. Precisely, layer one and two matches
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 5dac427..479f5e6 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -56,7 +56,8 @@ static void explain(void)
" code ICMP-CODE }\n"
" enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
" enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
- " enc_key_id [ KEY-ID ] }\n"
+ " enc_key_id [ KEY-ID ] |\n"
+ " matching_flags MATCHING-FLAGS }\n"
" FILTERID := X:Y:Z\n"
" ACTION-SPEC := ... look at individual actions\n"
"\n"
@@ -99,6 +100,31 @@ static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
return 0;
}
+static int flower_parse_matching_flags(char *str, int type, int mask_type,
+ struct nlmsghdr *n)
+{
+ __u32 mtf, mtf_mask;
+ char *c;
+
+ c = strchr(str, '/');
+ if (c)
+ *c = '\0';
+
+ if (get_u32(&mtf, str, 0))
+ return -1;
+
+ if (c) {
+ if (get_u32(&mtf_mask, ++c, 0))
+ return -1;
+ } else {
+ mtf_mask = 0xffffffff;
+ }
+
+ addattr32(n, MAX_MSG, type, htonl(mtf));
+ addattr32(n, MAX_MSG, mask_type, htonl(mtf_mask));
+ return 0;
+}
+
static int flower_parse_ip_proto(char *str, __be16 eth_type, int type,
__u8 *p_ip_proto, struct nlmsghdr *n)
{
@@ -314,6 +340,16 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
return -1;
}
addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4);
+ } else if (matches(*argv, "matching_flags") == 0) {
+ NEXT_ARG();
+ ret = flower_parse_matching_flags(*argv,
+ TCA_FLOWER_KEY_FLAGS,
+ TCA_FLOWER_KEY_FLAGS_MASK,
+ n);
+ if (ret < 0) {
+ fprintf(stderr, "Illegal \"matching_flags\"\n");
+ return -1;
+ }
} else if (matches(*argv, "skip_hw") == 0) {
flags |= TCA_CLS_FLAGS_SKIP_HW;
} else if (matches(*argv, "skip_sw") == 0) {
@@ -604,6 +640,17 @@ static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto,
*p_ip_proto = ip_proto;
}
+static void flower_print_matching_flags(FILE *f, char *name,
+ struct rtattr *attr,
+ struct rtattr *mask_attr)
+{
+ if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
+ return;
+
+ fprintf(f, "\n %s 0x%08x/0x%08x", name, ntohl(rta_getattr_u32(attr)),
+ mask_attr ? ntohl(rta_getattr_u32(mask_attr)) : 0xffffffff);
+}
+
static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
struct rtattr *addr4_attr,
struct rtattr *mask4_attr,
@@ -754,6 +801,10 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
flower_print_key_id(f, "enc_key_id",
tb[TCA_FLOWER_KEY_ENC_KEY_ID]);
+ flower_print_matching_flags(f, "matching_flags",
+ tb[TCA_FLOWER_KEY_FLAGS],
+ tb[TCA_FLOWER_KEY_FLAGS_MASK]);
+
if (tb[TCA_FLOWER_FLAGS]) {
__u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
--
1.8.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox