From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:07
Hello,
The goal of this patch series is to add basic support for PPv2.2 in
the existing mvpp2 driver. mvpp2 currently supported the PPv2.1
version of the IP, used in the 32 bits Marvell Armada 375 SoC. PPv2.2
is an evolution of this IP block, used in the 64 bits Marvell Armada
7K/8K SoCs.
In order to ease the review, the introduction of PPv2.2 support has
been made into multiple small commits, with the final commit adding
the compatible string that makes the PPv2.2 support actually
usable. The series remain fully bisectable.
Here is a quick overview of the series:
- Patch 1 updates the Device Tree binding documentation.
- Patch 2 to 10 make improvements to the mvpp2 not directly related
to the PPv2.2 support, but useful to have as they cleanup some dead
code, fix a few issues, etc.
- Patch 11 switches the driver to build_skb(), which is needed to
support PPv2.2 (details in the commit log itself)
- Patch 12 makes the driver build on 64 bits platform.
- Patches 13 to 26 add the PPv2.2 support step by step.
- Patch 27 finally adds the compatible string, which makes the PPv2.2
support usable.
I'd like to thank Stefan Chulski and Marcin Wojtas, who helped me a
lot in the development of this patch series, by reviewing the patches,
and giving lots of useful hints to debug the driver on PPv2.2. Thanks!
Best regards,
Thomas
Thomas Petazzoni (27):
dt-bindings: net: update Marvell PPv2 binding for PPv2.2 support
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
net: mvpp2: add and use accessors for TX/RX descriptors
net: mvpp2: add ip_version field in "struct mvpp2"
net: mvpp2: introduce an intermediate union for the TX/RX descriptors
net: mvpp2: introduce PPv2.2 HW descriptors and adapt accessors
net: mvpp2: adjust the allocation/free of BM pools for PPv2.2
net: mvpp2: adapt the mvpp2_rxq_*_pool_set functions to PPv2.2
net: mvpp2: adapt mvpp2_defaults_set() to PPv2.2
net: mvpp2: adjust mvpp2_{rxq,txq}_init for PPv2.2
net: mvpp2: handle register mapping and access for PPv2.2
net: mvpp2: handle misc PPv2.1/PPv2.2 differences
net: mvpp2: add AXI bridge initialization for PPv2.2
net: mvpp2: rework RXQ interrupt group initialization for PPv2.2
net: mvpp2: adapt rxq distribution to PPv2.2
net: mvpp2: add support for an additional clock needed for PPv2.2
net: mvpp2: finally add the PPv2.2 compatible string
.../devicetree/bindings/net/marvell-pp2.txt | 66 +-
drivers/net/ethernet/marvell/Kconfig | 2 +-
drivers/net/ethernet/marvell/mvpp2.c | 940 ++++++++++++++++-----
3 files changed, 789 insertions(+), 219 deletions(-)
--
2.7.4
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:08
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 <redacted>
---
.../devicetree/bindings/net/marvell-pp2.txt | 66 ++++++++++++++++++----
1 file changed, 55 insertions(+), 11 deletions(-)
@@ -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 at f0000 { compatible = "marvell,armada-375-pp2";
@@ -59,3 +71,35 @@ ethernet at f0000 { phy-mode = "gmii"; }; };++Example for marvell,armada-7k-pp2:++cpm_ethernet: ethernet at 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 at 0 {+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;+ port-id = <0>;+ gop-port-id = <0>;+ status = "disabled";+ };++ eth1: eth at 1 {+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;+ port-id = <1>;+ gop-port-id = <2>;+ status = "disabled";+ };++ eth2: eth at 2 {+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;+ port-id = <2>;+ gop-port-id = <3>;+ status = "disabled";+ };+};
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:09
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:10
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 7 +++++++
1 file changed, 7 insertions(+)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:11
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:12
This commit remove a field of 'struct mvpp2_tx_queue' that is not used
anywhere.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 3 ---
1 file changed, 3 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:13
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 18 +++---------------
1 file changed, 3 insertions(+), 15 deletions(-)
@@ -930,10 +930,6 @@ struct mvpp2_bm_pool {/* Ports using BM pool */u32port_map;--/* Occupied buffers indicator */-atomic_tin_use;-intin_use_thresh;};structmvpp2_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);return0;}
@@ -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 */staticintmvpp2_rx_refill(structmvpp2_port*port,-structmvpp2_bm_pool*bm_pool,-u32bm,intis_recycle)+structmvpp2_bm_pool*bm_pool,u32bm){structsk_buff*skb;dma_addr_tphys_addr;-if(is_recycle&&-(atomic_read(&bm_pool->in_use)<bm_pool->in_use_thresh))-return0;-/* 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);+return0;}
@@ -5139,7 +5128,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,skb=(structsk_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");gotoerr_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);
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:14
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
@@ -3626,7 +3626,6 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,{structsk_buff*skb;inti,buf_size,total_size;-u32bm;dma_addr_tphys_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,return0;}-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 */
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:17
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:18
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 77 +++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 22 deletions(-)
@@ -3428,7 +3445,8 @@ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,if(!vaddr)break;-dev_kfree_skb_any((structsk_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 */-staticstructsk_buff*mvpp2_skb_alloc(structmvpp2_port*port,-structmvpp2_bm_pool*bm_pool,-dma_addr_t*buf_phys_addr,-gfp_tgfp_mask)+staticvoid*mvpp2_buf_alloc(structmvpp2_port*port,+structmvpp2_bm_pool*bm_pool,+dma_addr_t*buf_phys_addr,+gfp_tgfp_mask){-structsk_buff*skb;dma_addr_tphys_addr;+void*data;-skb=__dev_alloc_skb(bm_pool->pkt_size,gfp_mask);-if(!skb)+data=mvpp2_frag_alloc(bm_pool);+if(!data)returnNULL;-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);returnNULL;}*buf_phys_addr=phys_addr;-returnskb;+returndata;}/* Set pool number in a BM cookie */
@@ -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,staticintmvpp2_rx_refill(structmvpp2_port*port,structmvpp2_bm_pool*bm_pool,u32bm){-structsk_buff*skb;dma_addr_tphys_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);return0;}
@@ -5087,14 +5107,17 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,structmvpp2_rx_desc*rx_desc=mvpp2_rxq_next_desc_get(rxq);structmvpp2_bm_pool*bm_pool;structsk_buff*skb;+unsignedintfrag_size;dma_addr_tphys_addr;u32bm,rx_status;intpool,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=(structsk_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");+gotoerr_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);
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:19
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 <redacted>
---
drivers/net/ethernet/marvell/Kconfig | 2 +-
drivers/net/ethernet/marvell/mvpp2.c | 29 +++++++++++++++++------------
2 files changed, 18 insertions(+), 13 deletions(-)
@@ -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((unsignedlong)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",
@@ -3596,14 +3597,15 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)}/* Get pool number from a BM cookie */-staticinlineintmvpp2_bm_cookie_pool_get(u32cookie)+staticinlineintmvpp2_bm_cookie_pool_get(unsignedlongcookie){return(cookie>>MVPP2_BM_COOKIE_POOL_OFFS)&0xFF;}/* Release buffer to BM */staticinlinevoidmvpp2_bm_pool_put(structmvpp2_port*port,intpool,-u32buf_phys_addr,u32buf_virt_addr)+dma_addr_tbuf_phys_addr,+unsignedlongbuf_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);
@@ -3626,7 +3629,8 @@ static void mvpp2_bm_pool_mc_put(struct mvpp2_port *port, int pool,/* Refill BM pool */staticvoidmvpp2_pool_refill(structmvpp2_port*port,u32bm,-u32phys_addr,u32cookie)+dma_addr_tphys_addr,+unsignedlongcookie){intpool=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,+(unsignedlong)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,(unsignedlong)buf);return0;}
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:20
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 187 +++++++++++++++++++++++++----------
1 file changed, 137 insertions(+), 50 deletions(-)
@@ -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,+(unsignedlong)data);continue;}
@@ -5197,11 +5275,15 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,}staticinlinevoid-tx_desc_unmap_put(structdevice*dev,structmvpp2_tx_queue*txq,+tx_desc_unmap_put(structmvpp2_port*port,structmvpp2_tx_queue*txq,structmvpp2_tx_desc*desc){-dma_unmap_single(dev,desc->buf_phys_addr,-desc->data_size,DMA_TO_DEVICE);+dma_addr_tbuf_phys_addr=+mvpp2_txdesc_phys_addr_get(port,desc);+size_tbuf_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);gotoerror;}-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);}}
@@ -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;gotoout;}-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;gotoout;}
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:21
In preparation to the introduction for the support of PPv2.2 in the
mvpp2 driver, this commit adds an ip_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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:22
Since the format of the HW descriptors is different between PPv2.1 and
PPv2.2, this commit introduces an intermediate union, with for now
only the PPv2.1 descriptors. The bulk of the driver code only
manipulates opaque mvpp2_tx_desc and mvpp2_rx_desc pointers, and the
descriptors can only be accessed and modified through the accessor
functions. A follow-up commit will add the descriptor definitions for
PPv2.2.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 43 +++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 13 deletions(-)
@@ -745,7 +745,8 @@ struct mvpp2_port {#define MVPP2_RXD_L3_IP6 BIT(30)#define MVPP2_RXD_BUF_HDR BIT(31)-structmvpp2_tx_desc{+/* HW TX descriptor for PPv2.1 */+structmvpp21_tx_desc{u32command;/* Options used by HW for packet transmitting.*/u8packet_offset;/* the offset from the buffer beginning */u8phys_txq;/* destination queue ID */
@@ -756,7 +757,8 @@ struct mvpp2_tx_desc {u32reserved2;/* reserved (for future use) */};-structmvpp2_rx_desc{+/* HW RX descriptor for PPv2.1 */+structmvpp21_rx_desc{u32status;/* info about received packet */u16reserved1;/* parser_info (for future use, PnC) */u16data_size;/* size of received packet in bytes */
@@ -771,6 +773,21 @@ struct mvpp2_rx_desc {u32reserved8;};+/* Opaque type used by the driver to manipulate the HW TX and RX+*descriptors+*/+structmvpp2_tx_desc{+union{+structmvpp21_tx_descpp21;+};+};++structmvpp2_rx_desc{+union{+structmvpp21_rx_descpp21;+};+};+structmvpp2_txq_pcpu_buf{/* Transmitted SKB */structsk_buff*skb;
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:23
This commit adds the definition of the PPv2.2 HW descriptors, adjusts
the mvpp2_tx_desc and mvpp2_rx_desc structures accordingly, and adapts
the accessors to work on both PPv2.1 and PPv2.2.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 109 +++++++++++++++++++++++++++++++----
1 file changed, 98 insertions(+), 11 deletions(-)
@@ -773,18 +773,42 @@ struct mvpp21_rx_desc {u32reserved8;};+/* HW TX descriptor for PPv2.2 */+structmvpp22_tx_desc{+u32command;+u8packet_offset;+u8phys_txq;+u16data_size;+u64reserved1;+u64buf_phys_addr_ptp;+u64buf_cookie_misc;+};++/* HW RX descriptor for PPv2.2 */+structmvpp22_rx_desc{+u32status;+u16reserved1;+u16data_size;+u32reserved2;+u32reserved3;+u64buf_phys_addr_key_hash;+u64buf_cookie_misc;+};+/* Opaque type used by the driver to manipulate the HW TX and RX*descriptors*/structmvpp2_tx_desc{union{structmvpp21_tx_descpp21;+structmvpp22_tx_descpp22;};};structmvpp2_rx_desc{union{structmvpp21_rx_descpp21;+structmvpp22_rx_descpp22;};};
@@ -991,72 +1015,135 @@ static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)staticdma_addr_tmvpp2_txdesc_phys_addr_get(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc){-returntx_desc->pp21.buf_phys_addr;+if(port->priv->ip_version==MVPP21)+returntx_desc->pp21.buf_phys_addr;+else+returntx_desc->pp22.buf_phys_addr_ptp&DMA_BIT_MASK(40);}staticvoidmvpp2_txdesc_phys_addr_set(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc,dma_addr_tphys_addr){-tx_desc->pp21.buf_phys_addr=phys_addr;+if(port->priv->ip_version==MVPP21){+tx_desc->pp21.buf_phys_addr=phys_addr;+}else{+u64val=(u64)phys_addr;++tx_desc->pp22.buf_phys_addr_ptp&=~DMA_BIT_MASK(40);+tx_desc->pp22.buf_phys_addr_ptp|=val;+}}staticsize_tmvpp2_txdesc_size_get(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc){-returntx_desc->pp21.data_size;+if(port->priv->ip_version==MVPP21)+returntx_desc->pp21.data_size;+else+returntx_desc->pp22.data_size;}staticvoidmvpp2_txdesc_size_set(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc,size_tsize){-tx_desc->pp21.data_size=size;+if(port->priv->ip_version==MVPP21)+tx_desc->pp21.data_size=size;+else+tx_desc->pp22.data_size=size;}staticvoidmvpp2_txdesc_txq_set(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc,unsignedinttxq){-tx_desc->pp21.phys_txq=txq;+if(port->priv->ip_version==MVPP21)+tx_desc->pp21.phys_txq=txq;+else+tx_desc->pp22.phys_txq=txq;}staticvoidmvpp2_txdesc_cmd_set(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc,unsignedintcommand){-tx_desc->pp21.command=command;+if(port->priv->ip_version==MVPP21)+tx_desc->pp21.command=command;+else+tx_desc->pp22.command=command;}staticvoidmvpp2_txdesc_offset_set(structmvpp2_port*port,structmvpp2_tx_desc*tx_desc,unsignedintoffset){-tx_desc->pp21.packet_offset=offset;+if(port->priv->ip_version==MVPP21)+tx_desc->pp21.packet_offset=offset;+else+tx_desc->pp22.packet_offset=offset;}staticdma_addr_tmvpp2_rxdesc_phys_addr_get(structmvpp2_port*port,structmvpp2_rx_desc*rx_desc){-returnrx_desc->pp21.buf_phys_addr;+if(port->priv->ip_version==MVPP21)+returnrx_desc->pp21.buf_phys_addr;+else+returnrx_desc->pp22.buf_phys_addr_key_hash&DMA_BIT_MASK(40);}staticunsignedlongmvpp2_rxdesc_virt_addr_get(structmvpp2_port*port,structmvpp2_rx_desc*rx_desc){-returnrx_desc->pp21.buf_cookie;+/* PPv2.1 can only be used on 32 bits architectures, and there+*are32bitsinbuf_cookiewhichareenoughtostorethe+*fullvirtualaddress,sothingsareeasy.+*/+if(port->priv->ip_version==MVPP21){+returnrx_desc->pp21.buf_cookie;+}else{+/* On PPv2.2, the situation is more complicated,+*becausethereisonly40bitstostorethevirtual+*address,whichisnotsufficient.Soon64bits+*systems,weusephys_to_virt()togetthevirtual+*addressfromthephysicaladdress,whichisfine+*becausethekernellinearmappingincludesthe+*entire40bitsphysicaladdressspace.On32bits+*systemshowever,wecan'tusephys_to_virt(),but+*sincevirtualaddressesare32bitsonly,thereis+*enoughspaceintheRXdescriptorforthefull+*virtualaddress.+*/+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT+dma_addr_tdma_addr=+rx_desc->pp22.buf_phys_addr_key_hash&DMA_BIT_MASK(40);+phys_addr_tphys_addr=+dma_to_phys(port->dev->dev.parent,dma_addr);++return(unsignedlong)phys_to_virt(phys_addr);+#else+returnrx_desc->pp22.buf_cookie_misc&DMA_BIT_MASK(40);+#endif+}}staticsize_tmvpp2_rxdesc_size_get(structmvpp2_port*port,structmvpp2_rx_desc*rx_desc){-returnrx_desc->pp21.data_size;+if(port->priv->ip_version==MVPP21)+returnrx_desc->pp21.data_size;+else+returnrx_desc->pp22.data_size;}staticu32mvpp2_rxdesc_status_get(structmvpp2_port*port,structmvpp2_rx_desc*rx_desc){-returnrx_desc->pp21.status;+if(port->priv->ip_version==MVPP21)+returnrx_desc->pp21.status;+else+returnrx_desc->pp22.status;}staticvoidmvpp2_txq_inc_get(structmvpp2_txq_pcpu*txq_pcpu)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:24
This commit adjusts the allocation and freeing of BM pools to support
PPv2.2. This involves:
- Checking that the number of buffer pointers is a multiple of 16, as
required by the hardware.
- Adjusting the size of the DMA coherent area allocated for buffer
pointers. Indeed, PPv2.2 needs space for 2 pointers of 64-bits per
buffer, as opposed to 2 pointers of 32-bits per buffer in
PPv2.1. The size in bytes is now stored in a new field of the
mvpp2_bm_pool structure.
- On PPv2.2, the 32 high order bits of the BM pointer area physical
address must be programmed in the MVPP2_BM_HIGH_BASE_REG register.
- On PPv2.2, getting the physical and virtual address of each buffer
requires reading the MVPP2_BM_ADDR_HIGH_ALLOC to get the high order
bits of those addresses. A new utility function
mvpp2_bm_bufs_get_addrs() is introduced to handle this.
- On PPv2.2, releasing a buffer requires writing the high order 32 bits
of the physical address to MVPP2_BM_PHY_VIRT_HIGH_RLS_REG. We no
longer need to write the virtual address to MVPP2_BM_VIRT_RLS_REG.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 97 ++++++++++++++++++++++++++++++------
1 file changed, 82 insertions(+), 15 deletions(-)
@@ -957,6 +968,8 @@ struct mvpp2_bm_pool {/* Buffer Pointers Pool External (BPPE) size */intsize;+/* BPPE size in bytes */+intsize_bytes;/* Number of buffers for this pool */intbuf_num;/* Pool buffer size */
@@ -3558,11 +3571,23 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,structmvpp2*priv,structmvpp2_bm_pool*bm_pool,intsize){-intsize_bytes;u32val;-size_bytes=sizeof(u32)*size;-bm_pool->virt_addr=dma_alloc_coherent(&pdev->dev,size_bytes,+/* Number of buffer pointers must be a multiple of 16, as per+*hardwareconstraints+*/+if(!IS_ALIGNED(size,16))+return-EINVAL;++/* PPv2.1 needs 8 bytes per buffer pointer, PPv2.2 needs 16+*bytesperbufferpointer+*/+if(priv->ip_version==MVPP21)+bm_pool->size_bytes=2*sizeof(u32)*size;+else+bm_pool->size_bytes=2*sizeof(u64)*size;++bm_pool->virt_addr=dma_alloc_coherent(&pdev->dev,bm_pool->size_bytes,&bm_pool->phys_addr,GFP_KERNEL);if(!bm_pool->virt_addr)
@@ -3570,15 +3595,24 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,if(!IS_ALIGNED((unsignedlong)bm_pool->virt_addr,MVPP2_BM_POOL_PTR_ALIGN)){-dma_free_coherent(&pdev->dev,size_bytes,bm_pool->virt_addr,-bm_pool->phys_addr);+dma_free_coherent(&pdev->dev,bm_pool->size_bytes,+bm_pool->virt_addr,bm_pool->phys_addr);dev_err(&pdev->dev,"BM pool %d is not %d bytes aligned\n",bm_pool->id,MVPP2_BM_POOL_PTR_ALIGN);return-ENOMEM;}mvpp2_write(priv,MVPP2_BM_POOL_BASE_REG(bm_pool->id),-bm_pool->phys_addr);+lower_32_bits(bm_pool->phys_addr));+/* On PPv2.2, program the high order bits of the base address */+if(priv->ip_version==MVPP22){+if(sizeof(dma_addr_t)==8)+val=upper_32_bits(bm_pool->phys_addr)&+MVPP2_BM_HIGH_BASE_MASK;+else+val=0;+mvpp2_write(priv,MVPP2_BM_HIGH_BASE_REG,val);+}mvpp2_write(priv,MVPP2_BM_POOL_SIZE_REG(bm_pool->id),size);val=mvpp2_read(priv,MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
@@ -3606,6 +3640,27 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,mvpp2_write(priv,MVPP2_POOL_BUF_SIZE_REG(bm_pool->id),val);}+staticvoidmvpp2_bm_bufs_get_addrs(structdevice*dev,structmvpp2*priv,+structmvpp2_bm_pool*bm_pool,+dma_addr_t*paddr,unsignedlong*vaddr)+{+*paddr=mvpp2_read(priv,MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));+*vaddr=mvpp2_read(priv,MVPP2_BM_VIRT_ALLOC_REG);++#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT+if(priv->ip_version==MVPP22){+u32val;+u32paddr_highbits;++val=mvpp2_read(priv,MVPP2_BM_ADDR_HIGH_ALLOC);+paddr_highbits=(val&MVPP2_BM_ADDR_HIGH_PHYS_MASK);++*paddr|=(dma_addr_t)paddr_highbits<<32;+*vaddr=(unsignedlong)phys_to_virt(dma_to_phys(dev,*paddr));+}+#endif+}+/* Free all buffers from the pool */staticvoidmvpp2_bm_bufs_free(structdevice*dev,structmvpp2*priv,structmvpp2_bm_pool*bm_pool)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:25
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 <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:26
This commit modifies the mvpp2_defaults_set() function to not do the
loopback and FIFO threshold initialization, which are not needed for
PPv2.2.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
@@ -4205,16 +4205,18 @@ static void mvpp2_defaults_set(struct mvpp2_port *port){inttx_port_num,val,queue,ptxq,lrxq;-/* Configure port to loopback if needed */-if(port->flags&MVPP2_F_LOOPBACK)-mvpp2_port_loopback_set(port);--/* Update TX FIFO MIN Threshold */-val=readl(port->base+MVPP2_GMAC_PORT_FIFO_CFG_1_REG);-val&=~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;-/* Min. TX threshold must be less than minimal packet length */-val|=MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64-4-2);-writel(val,port->base+MVPP2_GMAC_PORT_FIFO_CFG_1_REG);+if(port->priv->ip_version==MVPP21){+/* Configure port to loopback if needed */+if(port->flags&MVPP2_F_LOOPBACK)+mvpp2_port_loopback_set(port);++/* Update TX FIFO MIN Threshold */+val=readl(port->base+MVPP2_GMAC_PORT_FIFO_CFG_1_REG);+val&=~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;+/* Min. TX threshold must be less than minimal packet length */+val|=MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64-4-2);+writel(val,port->base+MVPP2_GMAC_PORT_FIFO_CFG_1_REG);+}/* Disable Legacy WRR, Disable EJP, Release from reset */tx_port_num=mvpp2_egress_port(port);
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:27
In PPv2.2, the MVPP2_RXQ_DESC_ADDR_REG and MVPP2_TXQ_DESC_ADDR_REG
registers have a slightly different layout, because they need to contain
a 64-bit address for the RX and TX descriptor arrays. This commit
adjusts those functions accordingly.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:28
This commit adjusts the mvpp2 driver register mapping and access logic
to support PPv2.2, to handle a number of differences.
Due to how the registers are laid out in memory, the Device Tree binding
for the "reg" property is different:
- On PPv2.1, we had a first area for the common registers, and then one
area per port.
- On PPv2.2, we have a first area for the common registers, and a
second area for all the per-ports registers.
In addition, on PPv2.2, the area for the common registers is split into
so-called "address spaces" of 64 KB each. They allow to access the same
registers, but from different CPUs. Hence the introduction of cpu_base[]
in 'struct mvpp2', and the modification of the mvpp2_write() and
mvpp2_read() register accessors. For PPv2.1, the compatibility is
preserved by using an "address space" size of 0.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 78 +++++++++++++++++++++++++++++-------
1 file changed, 64 insertions(+), 14 deletions(-)
@@ -644,6 +652,13 @@ struct mvpp2 {/* Shared registers' base addresses */void__iomem*base;void__iomem*lms_base;+void__iomem*iface_base;++/* On PPv2.2, each CPU can access the base register through a+*separateaddressspace,each64KBapartfromeach+*other.+*/+void__iomem*cpu_base[MVPP2_MAX_CPUS];/* Common clocks */structclk*pp_clk;
@@ -1021,12 +1036,21 @@ static int txq_number = MVPP2_MAX_TXQ;staticvoidmvpp2_write(structmvpp2*priv,u32offset,u32data){-writel(data,priv->base+offset);+intcpu=get_cpu();++writel(data,priv->cpu_base[cpu]+offset);+put_cpu();}staticu32mvpp2_read(structmvpp2*priv,u32offset){-returnreadl(priv->base+offset);+intcpu=get_cpu();+u32val;++val=readl(priv->cpu_base[cpu]+offset);+put_cpu();++returnval;}staticdma_addr_tmvpp2_txdesc_phys_addr_get(structmvpp2_port*port,
@@ -6408,7 +6432,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,u32id;intfeatures;intphy_mode;-intpriv_common_regs_num=2;interr,i,cpu;dev=alloc_etherdev_mqs(sizeof(structmvpp2_port),txq_number,
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:29
This commit handles a few miscellaneous differences between PPv2.1 and
PPv2.2 in different areas, where code done for PPv2.1 doesn't apply for
PPv2.2 or needs to be adjusted (getting the MAC address, disabling PHY
polling, etc.).
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
@@ -6513,7 +6516,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,mac_from="device tree";ether_addr_copy(dev->dev_addr,dt_mac_addr);}else{-mvpp2_get_mac_address(port,hw_mac_addr);+if(priv->ip_version==MVPP21)+mvpp21_get_mac_address(port,hw_mac_addr);if(is_valid_ether_addr(hw_mac_addr)){mac_from="hardware";ether_addr_copy(dev->dev_addr,hw_mac_addr);
@@ -6533,7 +6537,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,dev_err(&pdev->dev,"failed to init port %d\n",id);gotoerr_free_stats;}-mvpp2_port_power_up(port);++if(priv->ip_version==MVPP21)+mvpp21_port_power_up(port);port->pcpu=alloc_percpu(structmvpp2_port_pcpu);if(!port->pcpu){
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:30
The PPv2.2 unit is connected to an AXI bus on Armada 7K/8K, so this
commit adds the necessary initialization of the AXI bridge.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 85 ++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:31
This commit adjusts how the MVPP2_ISR_RXQ_GROUP_REG register is
configured, since it changed between PPv2.1 and PPv2.2.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 45 ++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)
@@ -6407,7 +6421,18 @@ static int mvpp2_port_init(struct mvpp2_port *port)}/* Configure Rx queue group interrupt for this port */-mvpp2_write(priv,MVPP2_ISR_RXQ_GROUP_REG(port->id),rxq_number);+if(priv->ip_version==MVPP21)+mvpp2_write(priv,MVPP21_ISR_RXQ_GROUP_REG(port->id),+rxq_number);+else{+u32val;++val=(port->id<<MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);+mvpp2_write(priv,MVPP22_ISR_RXQ_GROUP_INDEX_REG,val);++val=(rxq_number<<MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);+mvpp2_write(priv,MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG,val);+}/* Create Rx descriptor rings */for(queue=0;queue<rxq_number;queue++){
@@ -6792,8 +6817,20 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)mvpp2_rx_fifo_init(priv);/* Reset Rx queue group interrupt configuration */-for(i=0;i<MVPP2_MAX_PORTS;i++)-mvpp2_write(priv,MVPP2_ISR_RXQ_GROUP_REG(i),rxq_number);+for(i=0;i<MVPP2_MAX_PORTS;i++){+if(priv->ip_version==MVPP21)+mvpp2_write(priv,MVPP21_ISR_RXQ_GROUP_REG(i),+rxq_number);+else{+u32val;++val=(i<<MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);+mvpp2_write(priv,MVPP22_ISR_RXQ_GROUP_INDEX_REG,val);++val=(rxq_number<<MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);+mvpp2_write(priv,MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG,val);+}+}if(priv->ip_version==MVPP21)writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:32
In PPv2.1, we have a maximum of 8 RXQs per port, with a default of 4
RXQs per port, and we were assigning RXQs 0->3 to the first port, 4->7
to the second port, 8->11 to the third port, etc.
In PPv2.2, we have a maximum of 32 RXQs per port, and we must allocate
RXQs from the range of 32 RXQs available for each port. So port 0 must
use RXQs in the range 0->31, port 1 in the range 32->63, etc.
This commit adapts the mvpp2 to this difference between PPv2.1 and
PPv2.2:
- The constant definition MVPP2_MAX_RXQ is replaced by a new field
'max_port_rxqs' in 'struct mvpp2', which stores the maximum number of
RXQs per port. This field is initialized during ->probe() depending
on the IP version.
- MVPP2_RXQ_TOTAL_NUM is removed, and instead we calculate the total
number of RXQs by multiplying the number of ports by the maximum of
RXQs per port. This was anyway used in only one place.
- In mvpp2_port_probe(), the calculation of port->first_rxq is adjusted
to cope with the different allocation strategy between PPv2.1 and
PPv2.2. Due to this change, the 'next_first_rxq' argument of this
function is no longer needed and is removed.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)
@@ -399,15 +399,9 @@/* Maximum number of TXQs used by single port */#define MVPP2_MAX_TXQ 8-/* Maximum number of RXQs used by single port */-#define MVPP2_MAX_RXQ 8-/* Dfault number of RXQs in use */#define MVPP2_DEFAULT_RXQ 4-/* Total number of RXQs available to all ports */-#define MVPP2_RXQ_TOTAL_NUM (MVPP2_MAX_PORTS * MVPP2_MAX_RXQ)-/* Max number of Rx descriptors */#define MVPP2_MAX_RXD 128
@@ -728,6 +722,9 @@ struct mvpp2 {/* HW IP Version */enum{MVPP21,MVPP22}ip_version;++/* Maximum number of RXQs per port */+unsignedintmax_port_rxqs;};structmvpp2_pcpu_stats{
@@ -6355,7 +6352,8 @@ static int mvpp2_port_init(struct mvpp2_port *port)structmvpp2_txq_pcpu*txq_pcpu;intqueue,cpu,err;-if(port->first_rxq+rxq_number>MVPP2_RXQ_TOTAL_NUM)+if(port->first_rxq+rxq_number>+MVPP2_MAX_PORTS*priv->max_port_rxqs)return-EINVAL;/* Disable port */
@@ -6533,7 +6530,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,port->priv=priv;port->id=id;-port->first_rxq=*next_first_rxq;+if(priv->ip_version==MVPP21)+port->first_rxq=port->id*rxq_number;+else+port->first_rxq=port->id*priv->max_port_rxqs;+port->phy_node=phy_node;port->phy_interface=phy_mode;
@@ -6625,8 +6626,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,}netdev_info(dev,"Using %s mac address %pM\n",mac_from,dev->dev_addr);-/* Increment the first Rx queue number to be used by the next port */-*next_first_rxq+=rxq_number;priv->port_list[id]=port;return0;
@@ -6772,7 +6771,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)u32val;/* Checks for hardware constraints */-if(rxq_number%4||(rxq_number>MVPP2_MAX_RXQ)||+if(rxq_number%4||(rxq_number>priv->max_port_rxqs)||(txq_number>MVPP2_MAX_TXQ)){dev_err(&pdev->dev,"invalid queue size parameter\n");return-EINVAL;
@@ -6861,7 +6860,7 @@ static int mvpp2_probe(struct platform_device *pdev)structdevice_node*port_node;structmvpp2*priv;structresource*res;-intport_count,first_rxq,cpu;+intport_count,cpu;interr;priv=devm_kzalloc(&pdev->dev,sizeof(structmvpp2),GFP_KERNEL);
@@ -6896,6 +6895,11 @@ static int mvpp2_probe(struct platform_device *pdev)priv->cpu_base[cpu]=priv->base+cpu*addr_space_sz;}+if(priv->ip_version==MVPP21)+priv->max_port_rxqs=8;+else+priv->max_port_rxqs=32;+priv->pp_clk=devm_clk_get(&pdev->dev,"pp_clk");if(IS_ERR(priv->pp_clk))returnPTR_ERR(priv->pp_clk);
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:33
The PPv2.2 variant of the network controller needs an additional
clock, the "MG clock" in order for the IP block to operate
properly. This commit adds support for this additional clock to the
driver, reworking as needed the error handling path.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
@@ -702,6 +702,7 @@ struct mvpp2 {/* Common clocks */structclk*pp_clk;structclk*gop_clk;+structclk*mg_clk;/* List of pointers to port structures */structmvpp2_port**port_list;
@@ -6916,6 +6917,18 @@ static int mvpp2_probe(struct platform_device *pdev)if(err<0)gotoerr_pp_clk;+if(priv->ip_version==MVPP22){+priv->mg_clk=devm_clk_get(&pdev->dev,"mg_clk");+if(IS_ERR(priv->mg_clk)){+err=PTR_ERR(priv->mg_clk);+gotoerr_gop_clk;+}++err=clk_prepare_enable(priv->mg_clk);+if(err<0)+gotoerr_gop_clk;+}+/* Get system's tclk rate */priv->tclk=clk_get_rate(priv->pp_clk);
@@ -6923,14 +6936,14 @@ static int mvpp2_probe(struct platform_device *pdev)err=mvpp2_init(pdev,priv);if(err<0){dev_err(&pdev->dev,"failed to initialize controller\n");-gotoerr_gop_clk;+gotoerr_mg_clk;}port_count=of_get_available_child_count(dn);if(port_count==0){dev_err(&pdev->dev,"no ports enabled\n");err=-ENODEV;-gotoerr_gop_clk;+gotoerr_mg_clk;}priv->port_list=devm_kcalloc(&pdev->dev,port_count,
From: Thomas Petazzoni <hidden> Date: 2016-12-21 11:16:34
Now that the mvpp2 driver has been modified to accommodate the support
for PPv2.2, we can finally advertise this support by adding the
appropriate compatible string.
Signed-off-by: Thomas Petazzoni <redacted>
---
drivers/net/ethernet/marvell/mvpp2.c | 4 ++++
1 file changed, 4 insertions(+)
Two things:
1) net-next is closed, please do not submit net-next material during
this time.
2) 27 patches is way too many to submit at one time, please keep your
patch series submissions to a small, reasonable size.
Thanks.
From: Thomas Petazzoni <hidden> Date: 2016-12-21 16:12:46
Hello,
On Wed, 21 Dec 2016 11:03:48 -0500 (EST), David Miller wrote:
1) net-next is closed, please do not submit net-next material during
this time.
I did not expect you to review these patches right now, as I know
net-next is closed. However I expect other people in the net community
and people interested in Marvell platforms to look at those patches,
potentially test them and give feedback.
2) 27 patches is way too many to submit at one time, please keep your
patch series submissions to a small, reasonable size.
OK, I will do some arbitrary cut in the series and send several
smaller series instead.
Thanks for the feedback,
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
From: Thomas Petazzoni <redacted>
Date: Wed, 21 Dec 2016 17:12:46 +0100
Hello,
On Wed, 21 Dec 2016 11:03:48 -0500 (EST), David Miller wrote:
quoted
1) net-next is closed, please do not submit net-next material during
this time.
I did not expect you to review these patches right now, as I know
net-next is closed. However I expect other people in the net community
and people interested in Marvell platforms to look at those patches,
potentially test them and give feedback.
From: Thomas Petazzoni <hidden> Date: 2016-12-21 17:04:00
Hello,
On Wed, 21 Dec 2016 18:02:52 +0100, Andrew Lunn wrote:
On Wed, Dec 21, 2016 at 12:16:21PM +0100, Thomas Petazzoni wrote:
quoted
In preparation to the introduction for the support of PPv2.2 in the
mvpp2 driver, this commit adds an ip_version field to the struct
mvpp2
When i read this, i was thinking IPv4 vs IPv6. It is a network driver after all.
Could you maybe call this hw_version?
Sure, will do. Thanks for the feedback!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com