From patchwork Wed Dec 28 16:46:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Petazzoni X-Patchwork-Id: 709367 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3tpdx60tv2z9sdn for ; Thu, 29 Dec 2016 03:49:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752045AbcL1QtK (ORCPT ); Wed, 28 Dec 2016 11:49:10 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:47959 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751927AbcL1QsD (ORCPT ); Wed, 28 Dec 2016 11:48:03 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 7693F2076E; Wed, 28 Dec 2016 17:47:23 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 49CDD206F5; Wed, 28 Dec 2016 17:47:23 +0100 (CET) From: Thomas Petazzoni To: netdev@vger.kernel.org, "David S. Miller" , devicetree@vger.kernel.org, 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@lists.infradead.org, Stefan Chulski , Marcin Wojtas , Thomas Petazzoni Subject: [PATCHv2 net-next 05/16] net: mvpp2: introduce PPv2.2 HW descriptors and adapt accessors Date: Wed, 28 Dec 2016 17:46:21 +0100 Message-Id: <1482943592-12556-6-git-send-email-thomas.petazzoni@free-electrons.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1482943592-12556-1-git-send-email-thomas.petazzoni@free-electrons.com> References: <1482943592-12556-1-git-send-email-thomas.petazzoni@free-electrons.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- drivers/net/ethernet/marvell/mvpp2.c | 109 +++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index a37ff50..0e00ec0 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -773,18 +773,42 @@ struct mvpp21_rx_desc { u32 reserved8; }; +/* HW TX descriptor for PPv2.2 */ +struct mvpp22_tx_desc { + u32 command; + u8 packet_offset; + u8 phys_txq; + u16 data_size; + u64 reserved1; + u64 buf_phys_addr_ptp; + u64 buf_cookie_misc; +}; + +/* HW RX descriptor for PPv2.2 */ +struct mvpp22_rx_desc { + u32 status; + u16 reserved1; + u16 data_size; + u32 reserved2; + u32 reserved3; + u64 buf_phys_addr_key_hash; + u64 buf_cookie_misc; +}; + /* Opaque type used by the driver to manipulate the HW TX and RX * descriptors */ struct mvpp2_tx_desc { union { struct mvpp21_tx_desc pp21; + struct mvpp22_tx_desc pp22; }; }; struct mvpp2_rx_desc { union { struct mvpp21_rx_desc pp21; + struct mvpp22_rx_desc pp22; }; }; @@ -991,72 +1015,135 @@ static u32 mvpp2_read(struct mvpp2 *priv, u32 offset) static dma_addr_t mvpp2_txdesc_phys_addr_get(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc) { - return tx_desc->pp21.buf_phys_addr; + if (port->priv->hw_version == MVPP21) + return tx_desc->pp21.buf_phys_addr; + else + return tx_desc->pp22.buf_phys_addr_ptp & DMA_BIT_MASK(40); } static void mvpp2_txdesc_phys_addr_set(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc, dma_addr_t phys_addr) { - tx_desc->pp21.buf_phys_addr = phys_addr; + if (port->priv->hw_version == MVPP21) { + tx_desc->pp21.buf_phys_addr = phys_addr; + } else { + u64 val = (u64)phys_addr; + + tx_desc->pp22.buf_phys_addr_ptp &= ~DMA_BIT_MASK(40); + tx_desc->pp22.buf_phys_addr_ptp |= val; + } } static size_t mvpp2_txdesc_size_get(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc) { - return tx_desc->pp21.data_size; + if (port->priv->hw_version == MVPP21) + return tx_desc->pp21.data_size; + else + return tx_desc->pp22.data_size; } static void mvpp2_txdesc_size_set(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc, size_t size) { - tx_desc->pp21.data_size = size; + if (port->priv->hw_version == MVPP21) + tx_desc->pp21.data_size = size; + else + tx_desc->pp22.data_size = size; } static void mvpp2_txdesc_txq_set(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc, unsigned int txq) { - tx_desc->pp21.phys_txq = txq; + if (port->priv->hw_version == MVPP21) + tx_desc->pp21.phys_txq = txq; + else + tx_desc->pp22.phys_txq = txq; } static void mvpp2_txdesc_cmd_set(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc, unsigned int command) { - tx_desc->pp21.command = command; + if (port->priv->hw_version == MVPP21) + tx_desc->pp21.command = command; + else + tx_desc->pp22.command = command; } static void mvpp2_txdesc_offset_set(struct mvpp2_port *port, struct mvpp2_tx_desc *tx_desc, unsigned int offset) { - tx_desc->pp21.packet_offset = offset; + if (port->priv->hw_version == MVPP21) + tx_desc->pp21.packet_offset = offset; + else + tx_desc->pp22.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->pp21.buf_phys_addr; + if (port->priv->hw_version == MVPP21) + return rx_desc->pp21.buf_phys_addr; + else + return rx_desc->pp22.buf_phys_addr_key_hash & DMA_BIT_MASK(40); } static unsigned long mvpp2_rxdesc_virt_addr_get(struct mvpp2_port *port, struct mvpp2_rx_desc *rx_desc) { - return rx_desc->pp21.buf_cookie; + /* PPv2.1 can only be used on 32 bits architectures, and there + * are 32 bits in buf_cookie which are enough to store the + * full virtual address, so things are easy. + */ + if (port->priv->hw_version == MVPP21) { + return rx_desc->pp21.buf_cookie; + } else { + /* On PPv2.2, the situation is more complicated, + * because there is only 40 bits to store the virtual + * address, which is not sufficient. So on 64 bits + * systems, we use phys_to_virt() to get the virtual + * address from the physical address, which is fine + * because the kernel linear mapping includes the + * entire 40 bits physical address space. On 32 bits + * systems however, we can't use phys_to_virt(), but + * since virtual addresses are 32 bits only, there is + * enough space in the RX descriptor for the full + * virtual address. + */ +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + dma_addr_t dma_addr = + rx_desc->pp22.buf_phys_addr_key_hash & DMA_BIT_MASK(40); + phys_addr_t phys_addr = + dma_to_phys(port->dev->dev.parent, dma_addr); + + return (unsigned long)phys_to_virt(phys_addr); +#else + return rx_desc->pp22.buf_cookie_misc & DMA_BIT_MASK(40); +#endif + } } static size_t mvpp2_rxdesc_size_get(struct mvpp2_port *port, struct mvpp2_rx_desc *rx_desc) { - return rx_desc->pp21.data_size; + if (port->priv->hw_version == MVPP21) + return rx_desc->pp21.data_size; + else + return rx_desc->pp22.data_size; } static u32 mvpp2_rxdesc_status_get(struct mvpp2_port *port, struct mvpp2_rx_desc *rx_desc) { - return rx_desc->pp21.status; + if (port->priv->hw_version == MVPP21) + return rx_desc->pp21.status; + else + return rx_desc->pp22.status; } static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)