From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752986AbcFBIMd (ORCPT ); Thu, 2 Jun 2016 04:12:33 -0400 Received: from mail-by2on0070.outbound.protection.outlook.com ([207.46.100.70]:41651 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932152AbcFBIMK convert rfc822-to-8bit (ORCPT ); Thu, 2 Jun 2016 04:12:10 -0400 X-Greylist: delayed 1091 seconds by postgrey-1.27 at vger.kernel.org; Thu, 02 Jun 2016 04:12:10 EDT Authentication-Results: spf=pass (sender IP is 204.128.141.23) smtp.mailfrom=infinera.com; buserror.net; dkim=none (message not signed) header.d=none;buserror.net; dmarc=bestguesspass action=none header.from=infinera.com; From: Joakim Tjernlund To: "oss@buserror.net" , "qiang.zhao@nxp.com" CC: "linuxppc-dev@lists.ozlabs.org" , "netdev@vger.kernel.org" , "linux-kernel@vger.kernel.org" , "xiaobo.xie@nxp.com" Subject: Re: [Patch v2 5/5] drivers/net: support hdlc function for QE-UCC Thread-Topic: [Patch v2 5/5] drivers/net: support hdlc function for QE-UCC Thread-Index: AQHRvHaj5Qr9tSZ4lE+oO2uO18W6P5/WP9UA Date: Thu, 2 Jun 2016 07:37:32 +0000 Message-ID: <1464853088.7659.21.camel@infinera.com> References: <1464831901-15913-1-git-send-email-qiang.zhao@nxp.com> <1464831901-15913-5-git-send-email-qiang.zhao@nxp.com> In-Reply-To: <1464831901-15913-5-git-send-email-qiang.zhao@nxp.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.100.99.93] Content-Type: text/plain; charset="iso-8859-15" Content-ID: <811FE51A6C76974DA197180C26350375@infinera.com> Content-Transfer-Encoding: 8BIT MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:204.128.141.23;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(199003)(189002)(24454002)(377424004)(77096005)(8666004)(2900100001)(33646002)(2950100001)(8676002)(8936002)(16796002)(6806005)(5008740100001)(10400500002)(19580395003)(8746002)(53416004)(106466001)(19580405001)(106116001)(5001770100001)(103116003)(586003)(189998001)(86362001)(87936001)(54356999)(47776003)(50986999)(2906002)(102836003)(3846002)(6116002)(50466002)(4326007)(92566002)(5004730100002)(11100500001)(5001970100001)(5003600100002)(36756003)(2501003)(23756003)(76176999)(7059030);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR10MB0523;H:owa.infinera.com;FPR:;SPF:Pass;MLV:sfv;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11FD009;1:DkCWpoXTvbYyvmh8xLPpWpClurVf/CPaG/u/qkmiPKX3mM10uPUWFlYOrAcyZP9pGOb86FgoIeZRWMh3XulvUPpecXAfzUypUA7av4Xo/jD4YbiGTtdM17F+XUZzzqWZfdB/A8dMgWNY5UwxFvjuh8xPY1h7lmmpQL/gsSdfRk6cEtK1xhKekIwCM5wTFOrj0+yrWfmQm+Iv+IGKaB3QZpDgBDCJKuWqqfKBW7RP1QU1hopwHvp+xxwhdp9TG3Cyot/fnN8lP9Xxa1zk24xox5tLNDdoWrXExx2aO3s8ryG6zr5TgLzG2/4XIob2icS/FRkMvlkJJsWgrmIBFhJNDjbP0mnvUIprJksB7oL+mLSibXcAgL08osEvhxYPzHc+booZ+2Xetfeqx5FY0Er0dqrePQOXIuLiIYfUY1rufS4OmXb+/mmNh8n7BTG2dJdB3twf/+rnNMNgfe+Vl5e8BfBcKS5JB5q4d5FU2l2yEkpf5038uMlHuCeOdACncFaS X-MS-Office365-Filtering-Correlation-Id: 9981d038-0d5c-4fe8-e0b2-08d38ab8dab3 X-Microsoft-Exchange-Diagnostics: 1;CY1PR10MB0523;2:7KD7PcXxwurzUxe1xVxbJsETXQwFkFsqpGTcLd3uxeJwZ9q6KEQ4C5fbI8gKYbrHxszDv25bKFuScz7OuD/zFKSRuHVnIHitNsfoq0b16Btbf//j5qCvSbdY4nnKkanXTduYoyMMdSLGKvnXeQzCHhYdamauHC4J9EvcM7VwJrRiXZf0gzEyUrWgvui+eRIi;3:GXHTYwfffaW75sSWbCVsoAw9/Lshv0mHwPhaqR48OLmykLZ4JVhyJSVcMOfzoPs2SKNITf14srS+DdH79LDY7NQZssOz3sOg5YcmDrRoX6D1RkYqhRbWvqoITSTCCrwUA8qACfu6psYy8qUXElQ8/SzsuOeT8n6Vv0bmylqoF2hZk0b4loFwkANJhEeVhUz3Y+DzCeXgwrIOHNLIql319jCxyGGENTUwhDrIGK3M6J8tmBNwS3uAk7bGlc2NVSoKXXHhN0Y+JfcNSqvPh0OFcQ==;25:HJFgE1BCS1ijGv0jwABw0L3TJontkUPj3XckVCR/KlgJhYdINQSbbc+5fzsXmPC0v+IweWIQklk8r2hEQ87N942l4flITehqFGlT6PWajhxZLtelXm1cS2fMFJ6fBTFJyLfY9dkOy+vE/Tidar6UcOu2FYNt4FDMfSUZS3uLigZy2YswjLTZ/4Lp7Oi1fKPvJr44bXADZR3Hon/aZTT7rAMMBAvgB2eZAR4wC73UcLPyvocZTGDXMVDPACoYKAok2vyujuPHqTm2ImaisDmxAe9QbQ7qdyqWwTsxXqHN5VcgA0RSvdEcp9gbqgBOWLZ5u5XR7DNGrTnIC2r8COi/MtNd1osqGWi1+cIkMlpDudCm6RQEMLQP7rq4hZrmdA4StKuglKcHumiF+9vd2xU7p3WYxKJvxEOlv0gFoqjOHRY= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501002);SRVR:CY1PR10MB0523; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(9452136761055)(65623756079841)(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(13018025)(13024025)(13015025)(13017025)(13023025)(8121501046)(10201501046)(3002001);SRVR:CY1PR10MB0523;BCL:0;PCL:0;RULEID:;SRVR:CY1PR10MB0523; X-Microsoft-Exchange-Diagnostics: 1;CY1PR10MB0523;4:psb0g47TNnWZTqj9L1/Ox4v4SXbllZn/BIkOXlZHZXKp/IwBmKpTiE59Bv32H0FBPp7Kf4Gvb/dWlNcIJy3aw0d3q9feD9g28iiUzeemkJXnPo+ez57K8ZD/m5azqMkksM9cDTPg+IluKwTtag3eYq8K+xLTrlooQ4/rxrs5HszAi4lMTasTYCw0jhX2rxhBetAK4XHJLXplfkHtmTUg02RglGcp1VFpB3k94rhdkTVAzJIVTFhb3CcdH8T9sBife+FVl2XaGu3EysMyS/rONAsqRS4RjV0icPIDf3ypj7/SvI52FB9Dcpbta+BfDN1TWYOT/YmSa4mkngeBUOP4iF7O/T5WAHnuiXyrAFpofvJFgFkRHqnM3UspXEuIWUTlcOCY2Y7EjZgPcFmJJ4vnHZZU+cfj0cxI4esYLn+DLAe4ijIy5gDkkCr2g306d3XAfqytICejx+xiXRgtbCDvFeY0kv8YT9IqzjlugR/xddQdCVv5nP8f0HTNo6c3h/QVk/OUNZ0WHP8Ou2Q3UQUwWaLBMWiG0mGrK5xl8F7sG4ikyNWkzdFver+WXLDpemdJ X-Forefront-PRVS: 0961DF5286 X-Microsoft-Exchange-Diagnostics: =?iso-8859-15?Q?1;CY1PR10MB0523;23:/YZaFWcKCI0vKk0W395i9vTVy4HJ6kcIwUzJBh?= =?iso-8859-15?Q?S1rx0IXwFOglOhCDGKVRoTfal79KcLtKUO1ijAtbo87fkVmiJJg1a0wEN?= =?iso-8859-15?Q?CKwSwf0SRbVQ2oweJR6EI+7/XiHWO8I0fX7IWB8JUU2jfLzyCY4AbHmhi?= =?iso-8859-15?Q?0EMwQGOBTQ0aByDqsf7p0ZURZuVg0DOiZJbgE67hTs/HVqpHzs1nt48nh?= =?iso-8859-15?Q?scO9FkFwxDmMtChGl5BTOyaYTorrC4ogLtwjYcQ2lpfrjM5OvJqjShvRx?= =?iso-8859-15?Q?+peMc3VvwjuMlnT5klNcvK6+WqYqEm9NNODvEMXR5G9clEMGifjaGsXjv?= =?iso-8859-15?Q?QSTkh1GdBxL6wA3kYBCnwzoeIw5FEVHs6Q321NEORr4SgXsCx3QtJTiCa?= =?iso-8859-15?Q?+J6B2fWwSo5VvWLQbaz/7NvRpJAA+tVqbZGoR445kS/MMOLICZ6D35aJw?= =?iso-8859-15?Q?qGGC3ckLipkTK1Df72fk53TDoO6fwLm3Wr8RUkmL3Qks8wtaRKQj5uG+M?= =?iso-8859-15?Q?7Ag7E11E2C/HNlxLFDBxMJBEranmwykQCxoYYrbblayU5kpXuhsiaxyDI?= =?iso-8859-15?Q?9s4alUk9HMRQqzeopoFR28gztFzhgglbXaB61gZ4QmJcY4laEQ5ch23Pv?= =?iso-8859-15?Q?FY6f6YUAr8rWSFcGEd8YlxBbYvu0TBieaAV/T9npg/y/1uoCyhh0XnsKO?= =?iso-8859-15?Q?aILCKgCr015oi6JuRCcZrQng8LIN4jFB35XqWxzIRzhLqw8svtZFVcD76?= =?iso-8859-15?Q?3IBifj0AcgCEcn69JEGdHpFCcYXMVKM1IY2XR4N5Nnn5htQeDVdRDdZws?= =?iso-8859-15?Q?u6ivdDMgUyvtg/htI0nm/wmZ5f57W5sGFAPn4tAsqvXM1vHK4idvGH+J/?= =?iso-8859-15?Q?xxgFTzoL9ioqASmJewhbPiRPGkH8z43zjofCN9zmMO9GPK3GYGK130NYJ?= =?iso-8859-15?Q?WpBhBCoJc0IJ42ZpLxNkpvoefxPA5h+ZfknPidVFK2IouaaWXrmmYMUQG?= =?iso-8859-15?Q?XQ9Jq7D83yR27axXJAXwbiCfuNTvYQfmTvY7Swlpi60j+82d6sBSzn87B?= =?iso-8859-15?Q?YCrHnWisfQBeBhGJpMdj6dnjOjEusYUHgiqohMnoN1hWeWtLmpdKWrUTg?= =?iso-8859-15?Q?ke+wW4lQxxbTQ+FAJp0sm4DdZ9i21hRQL/PJkDNu4ofPCqCzInDJugKWf?= =?iso-8859-15?Q?d/fgM0DVR7dFdnukcfiJADfR6ScGxHOK6K4MP/7sk/9pTtKPoFZ0842bQ?= =?iso-8859-15?Q?k7tomXSXJOwrYyAmIuvOAZzC0J3284VaSb2rkM4CswiKXVXYKMLv6L6SH?= =?iso-8859-15?Q?Q7dh6LckgDQe+XVj8U6VhmoaBtBbGKof0gUapkkVKiiw9?= X-Microsoft-Exchange-Diagnostics: 1;CY1PR10MB0523;5:BVyuZo7Op4vLbQxZ/5hPOZRXGLQoYQCc3nKr9h55QbEv0tGJ50nGNaoXU6Ahud1lYTFF38RjDgYZnf5WRNyM0Mugjy+ymDs1Qq7QJItrSLbYlZGx3whpE1RzsXfCFFhnrBDFZfRh0uf5kituZ5trcw==;24:8sZDgpBYIBuknvaCDm580wCJiKvueQ3SLHCNWDDQ0j/x5qUx93bj50TDmoDdoYyMJzWoy25xQ32eAbKb1ik8qBjeKFZgR7BD7wIb5XxlyMo=;7:iAjn2Wj73PpRwjI6H/oaM1ZMRyM+yvrjkxsKzo5BlBV7nikkc13xZ76en5wTQzAvOf+WCH3b4ugvgtBa64AB9S2v+cKNfijlfSbnQqPqpYte/bwuoF0oDz861B9oQuSsP+0s3HIwwhMVfgxZaeNQAUsIGkFXBwMvaGTx4OlYUf5yE+Gr12n51HYqriIFEvhv SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: infinera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Jun 2016 07:38:13.4713 (UTC) X-MS-Exchange-CrossTenant-Id: 285643de-5f5b-4b03-a153-0ae2dc8aaf77 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=285643de-5f5b-4b03-a153-0ae2dc8aaf77;Ip=[204.128.141.23];Helo=[owa.infinera.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR10MB0523 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 2016-06-02 at 09:45 +0800, Zhao Qiang wrote: > The driver add hdlc support for Freescale QUICC Engine. > It support NMSI and TSA mode. > > Signed-off-by: Zhao Qiang > --- > Changes for v2: > - remove useless code. > - remove Unnecessary casts > - return IRQ_NONE when there are no interrupt > - remove Useless comments > >  MAINTAINERS                    |    7 + >  drivers/net/wan/Kconfig        |   11 + >  drivers/net/wan/Makefile       |    1 + >  drivers/net/wan/fsl_ucc_hdlc.c | 1189 ++++++++++++++++++++++++++++++++++++++++ >  drivers/net/wan/fsl_ucc_hdlc.h |  147 +++++ >  include/soc/fsl/qe/qe.h        |    1 + >  include/soc/fsl/qe/ucc_fast.h  |   21 +- >  7 files changed, 1375 insertions(+), 2 deletions(-) >  create mode 100644 drivers/net/wan/fsl_ucc_hdlc.c >  create mode 100644 drivers/net/wan/fsl_ucc_hdlc.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 74bbff3..bdada16 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4572,6 +4572,13 @@ F: drivers/net/ethernet/freescale/gianfar* >  X: drivers/net/ethernet/freescale/gianfar_ptp.c >  F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt >   > +FREESCALE QUICC ENGINE UCC HDLC DRIVER > +M: Zhao Qiang > +L: netdev@vger.kernel.org > +L: linuxppc-dev@lists.ozlabs.org > +S: Maintained > +F: drivers/net/wan/fsl_ucc_hdlc* > + >  FREESCALE QUICC ENGINE UCC UART DRIVER >  M: Timur Tabi >  L: linuxppc-dev@lists.ozlabs.org > diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig > index a2fdd15..9e314b7 100644 > --- a/drivers/net/wan/Kconfig > +++ b/drivers/net/wan/Kconfig > @@ -280,6 +280,17 @@ config DSCC4 >     To compile this driver as a module, choose M here: the >     module will be called dscc4. >   > +config FSL_UCC_HDLC > + tristate "Freescale QUICC Engine HDLC support" > + depends on HDLC > + depends on QUICC_ENGINE > + help > +   Driver for Freescale QUICC Engine HDLC controller. The driver > +   supports HDLC in NMSI and TDM mode. > + > +   To compile this driver as a module, choose M here: the > +   module will be called fsl_ucc_hdlc. > + >  config DSCC4_PCISYNC >   bool "Etinc PCISYNC features" >   depends on DSCC4 > diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile > index c135ef4..25fec40 100644 > --- a/drivers/net/wan/Makefile > +++ b/drivers/net/wan/Makefile > @@ -32,6 +32,7 @@ obj-$(CONFIG_WANXL) += wanxl.o >  obj-$(CONFIG_PCI200SYN) += pci200syn.o >  obj-$(CONFIG_PC300TOO) += pc300too.o >  obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o > +obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o >   >  clean-files := wanxlfw.inc >  $(obj)/wanxl.o: $(obj)/wanxlfw.inc > diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c > new file mode 100644 > index 0000000..f72634d > --- /dev/null > +++ b/drivers/net/wan/fsl_ucc_hdlc.c > @@ -0,0 +1,1189 @@ > +/* Freescale QUICC Engine HDLC Device Driver > + * > + * Copyright 2016 Freescale Semiconductor Inc. > + * > + * This program is free software; you can redistribute  it and/or modify it > + * under  the terms of  the GNU General  Public License as published by the > + * Free Software Foundation;  either version 2 of the  License, or (at your > + * option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "fsl_ucc_hdlc.h" > + > +#define DRV_DESC "Freescale QE UCC HDLC Driver" > +#define DRV_NAME "ucc_hdlc" > + > +#define TDM_PPPOHT_SLIC_MAXIN > +#define BROKEN_FRAME_INFO > + > +static struct ucc_tdm_info utdm_primary_info = { > + .uf_info = { > + .tsa = 0, > + .cdp = 0, > + .cds = 1, > + .ctsp = 1, > + .ctss = 1, > + .revd = 0, > + .urfs = 256, > + .utfs = 256, > + .urfet = 128, > + .urfset = 192, > + .utfet = 128, > + .utftt = 0x40, > + .ufpt = 256, > + .mode = UCC_FAST_PROTOCOL_MODE_HDLC, > + .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, > + .tenc = UCC_FAST_TX_ENCODING_NRZ, > + .renc = UCC_FAST_RX_ENCODING_NRZ, > + .tcrc = UCC_FAST_16_BIT_CRC, > + .synl = UCC_FAST_SYNC_LEN_NOT_USED, > + }, > + > + .si_info = { > +#ifdef TDM_PPPOHT_SLIC_MAXIN > + .simr_rfsd = 1, > + .simr_tfsd = 2, > +#else > + .simr_rfsd = 0, > + .simr_tfsd = 0, > +#endif > + .simr_crt = 0, > + .simr_sl = 0, > + .simr_ce = 1, > + .simr_fe = 1, > + .simr_gm = 0, > + }, > +}; > + > +static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM]; > + > +static int uhdlc_init(struct ucc_hdlc_private *priv) > +{ > + struct ucc_tdm_info *ut_info; > + struct ucc_fast_info *uf_info; > + u32 cecr_subblock; > + u16 bd_status; > + int ret, i; > + void *bd_buffer; > + dma_addr_t bd_dma_addr; > + u32 riptr; > + u32 tiptr; > + u32 gumr; > + > + ut_info = priv->ut_info; > + uf_info = &ut_info->uf_info; > + > + if (priv->tsa) { > + uf_info->tsa = 1; > + uf_info->ctsp = 1; > + } > + uf_info->uccm_mask = ((UCC_HDLC_UCCE_RXB | UCC_HDLC_UCCE_RXF | > + UCC_HDLC_UCCE_TXB) << 16); > + > + ret = ucc_fast_init(uf_info, &priv->uccf); > + if (ret) { > + dev_err(priv->dev, "Failed to init uccf."); > + return ret; > + } > + > + priv->uf_regs = priv->uccf->uf_regs; > + ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX); > + > + /* Loopback mode */ > + if (priv->loopback) { > + dev_info(priv->dev, "Loopback Mode\n"); > + gumr = ioread32be(&priv->uf_regs->gumr); > + gumr |= (UCC_FAST_GUMR_LOOPBACK | UCC_FAST_GUMR_CDS | > +  UCC_FAST_GUMR_TCI); > + gumr &= ~(UCC_FAST_GUMR_CTSP | UCC_FAST_GUMR_RSYN); > + iowrite32be(gumr, &priv->uf_regs->gumr); > + } > + > + /* Initialize SI */ > + if (priv->tsa) > + ucc_tdm_init(priv->utdm, priv->ut_info); > + > + /* Write to QE CECR, UCCx channel to Stop Transmission */ > + cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); > + ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock, > +    QE_CR_PROTOCOL_UNSPECIFIED, 0); > + > + /* Set UPSMR normal mode (need fixed)*/ > + iowrite32be(0, &priv->uf_regs->upsmr); > + > + priv->rx_ring_size = RX_BD_RING_LEN; > + priv->tx_ring_size = TX_BD_RING_LEN; > + /* Alloc Rx BD */ > + priv->rx_bd_base = dma_alloc_coherent(priv->dev, > + RX_BD_RING_LEN * sizeof(struct qe_bd *), > + &priv->dma_rx_bd, GFP_KERNEL); > + > + if (!priv->rx_bd_base) { > + dev_err(priv->dev, "Cannot allocate MURAM memory for RxBDs\n"); > + ret = -ENOMEM; > + goto rxbd_alloc_error; > + } > + > + /* Alloc Tx BD */ > + priv->tx_bd_base = dma_alloc_coherent(priv->dev, > + TX_BD_RING_LEN * sizeof(struct qe_bd *), > + &priv->dma_tx_bd, GFP_KERNEL); > + > + if (!priv->tx_bd_base) { > + dev_err(priv->dev, "Cannot allocate MURAM memory for TxBDs\n"); > + ret = -ENOMEM; > + goto txbd_alloc_error; > + } > + > + /* Alloc parameter ram for ucc hdlc */ > + priv->ucc_pram_offset = qe_muram_alloc(sizeof(priv->ucc_pram), > + ALIGNMENT_OF_UCC_HDLC_PRAM); > + > + if (priv->ucc_pram_offset < 0) { > + dev_err(priv->dev, "Can not allocate MURAM for hdlc prameter.\n"); > + ret = -ENOMEM; > + goto pram_alloc_error; > + } > + > + priv->rx_skbuff = kzalloc(priv->rx_ring_size * sizeof(*priv->rx_skbuff), > +   GFP_KERNEL); > + if (!priv->rx_skbuff) > + goto rx_skb_alloc_error; > + > + priv->tx_skbuff = kzalloc(priv->tx_ring_size * sizeof(*priv->tx_skbuff), > +   GFP_KERNEL); > + if (!priv->tx_skbuff) > + goto tx_skb_alloc_error; > + > + priv->skb_curtx = 0; > + priv->skb_dirtytx = 0; > + priv->curtx_bd = priv->tx_bd_base; > + priv->dirty_tx = priv->tx_bd_base; > + priv->currx_bd = priv->rx_bd_base; > + priv->currx_bdnum = 0; > + > + /* init parameter base */ > + cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); > + ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock, > +    QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset); > + > + priv->ucc_pram = (struct ucc_hdlc_param __iomem *) > + qe_muram_addr(priv->ucc_pram_offset); > + > + /* Zero out parameter ram */ > + memset_io(priv->ucc_pram, 0, sizeof(struct ucc_hdlc_param)); > + > + /* Alloc riptr, tiptr */ > + riptr = qe_muram_alloc(32, 32); > + if (riptr < 0) { > + dev_err(priv->dev, "Cannot allocate MURAM mem for Receive internal temp data pointer\n"); > + ret = -ENOMEM; > + goto riptr_alloc_error; > + } > + > + tiptr = qe_muram_alloc(32, 32); > + if (tiptr < 0) { > + dev_err(priv->dev, "Cannot allocate MURAM mem for Transmit internal temp data pointer\n"); > + ret = -ENOMEM; > + goto tiptr_alloc_error; > + } > + > + /* Set RIPTR, TIPTR */ > + iowrite16be(riptr, &priv->ucc_pram->riptr); > + iowrite16be(tiptr, &priv->ucc_pram->tiptr); > + > + /* Set MRBLR */ > + iowrite16be(MAX_RX_BUF_LENGTH, &priv->ucc_pram->mrblr); > + > + /* Set RBASE, TBASE */ > + iowrite32be(priv->dma_rx_bd, &priv->ucc_pram->rbase); > + iowrite32be(priv->dma_tx_bd, &priv->ucc_pram->tbase); > + > + /* Set RSTATE, TSTATE */ > + iowrite32be(BMR_GBL | BMR_BIG_ENDIAN, &priv->ucc_pram->rstate); > + iowrite32be(BMR_GBL | BMR_BIG_ENDIAN, &priv->ucc_pram->tstate); > + > + /* Set C_MASK, C_PRES for 16bit CRC */ > + iowrite32be(CRC_16BIT_MASK, &priv->ucc_pram->c_mask); > + iowrite32be(CRC_16BIT_PRES, &priv->ucc_pram->c_pres); > + > + iowrite16be(MAX_FRAME_LENGTH, &priv->ucc_pram->mflr); > + iowrite16be(DEFAULT_RFTHR, &priv->ucc_pram->rfthr); > + iowrite16be(DEFAULT_RFTHR, &priv->ucc_pram->rfcnt); > + iowrite16be(DEFAULT_ADDR_MASK, &priv->ucc_pram->hmask); > + iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr1); > + iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr2); > + iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr3); > + iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4); > + > + /* Get BD buffer */ > + bd_buffer = dma_alloc_coherent(priv->dev, > +        (RX_BD_RING_LEN + TX_BD_RING_LEN) * > +        MAX_RX_BUF_LENGTH, > +        &bd_dma_addr, GFP_KERNEL); > + > + if (!bd_buffer) { > + dev_err(priv->dev, "Could not allocate buffer descriptors\n"); > + ret = -ENOMEM; > + goto bd_alloc_error; > + } > + > + memset(bd_buffer, 0, (RX_BD_RING_LEN + TX_BD_RING_LEN) > + * MAX_RX_BUF_LENGTH); > + > + priv->rx_buffer = bd_buffer; > + priv->tx_buffer = bd_buffer + RX_BD_RING_LEN * MAX_RX_BUF_LENGTH; > + > + priv->dma_rx_addr = bd_dma_addr; > + priv->dma_tx_addr = bd_dma_addr + RX_BD_RING_LEN * MAX_RX_BUF_LENGTH; > + > + for (i = 0; i < RX_BD_RING_LEN; i++) { > + if (i < (RX_BD_RING_LEN - 1)) > + bd_status = R_E_S | R_I_S; > + else > + bd_status = R_E_S | R_I_S | R_W_S; > + > + iowrite16be(bd_status, &priv->rx_bd_base[i].status); > + iowrite32be(priv->dma_rx_addr + i * MAX_RX_BUF_LENGTH, > +     &priv->rx_bd_base[i].buf); > + } > + > + for (i = 0; i < TX_BD_RING_LEN; i++) { > + if (i < (TX_BD_RING_LEN - 1)) > + bd_status =  T_I_S | T_TC_S; > + else > + bd_status =  T_I_S | T_TC_S | T_W_S; > + > + iowrite16be(bd_status, &priv->tx_bd_base[i].status); > + iowrite32be(priv->dma_tx_addr + i * MAX_RX_BUF_LENGTH, > +     &priv->tx_bd_base[i].buf); > + } > + > + return 0; > + > +bd_alloc_error: > + qe_muram_free(tiptr); > +tiptr_alloc_error: > + qe_muram_free(riptr); > +riptr_alloc_error: > + kfree(priv->tx_skbuff); > +tx_skb_alloc_error: > + kfree(priv->rx_skbuff); > +rx_skb_alloc_error: > + qe_muram_free(priv->ucc_pram_offset); > +pram_alloc_error: > + dma_free_coherent(priv->dev, > +   TX_BD_RING_LEN * sizeof(struct qe_bd), > +   priv->tx_bd_base, priv->dma_tx_bd); > +txbd_alloc_error: > + dma_free_coherent(priv->dev, > +   RX_BD_RING_LEN * sizeof(struct qe_bd), > +   priv->rx_bd_base, priv->dma_rx_bd); > +rxbd_alloc_error: > + ucc_fast_free(priv->uccf); > + > + return ret; > +} > + > +static netdev_tx_t ucc_hdlc_tx(struct sk_buff *skb, struct net_device *dev) > +{ > + hdlc_device *hdlc = dev_to_hdlc(dev); > + struct ucc_hdlc_private *priv = (struct ucc_hdlc_private *)hdlc->priv; > + struct qe_bd __iomem *bd; > + u16 bd_status; > + unsigned long flags; > + u8 *send_buf; > + int i; > + u16 *proto_head; > + > + switch (dev->type) { > + case ARPHRD_RAWHDLC: > + if (skb_headroom(skb) < HDLC_HEAD_LEN) { > + dev->stats.tx_dropped++; > + dev_kfree_skb(skb); > + netdev_err(dev, "No enough space for hdlc head\n"); > + return -ENOMEM; > + } > + > + skb_push(skb, HDLC_HEAD_LEN); > + > + proto_head = (u16 *)skb->data; > + *proto_head = htons(DEFAULT_HDLC_HEAD); > + > + dev->stats.tx_bytes += skb->len; > + break; > + > + case ARPHRD_PPP: > + proto_head = (u16 *)skb->data; > + if (*proto_head != htons(DEFAULT_PPP_HEAD)) { > + dev->stats.tx_dropped++; > + dev_kfree_skb(skb); > + netdev_err(dev, "Wrong ppp header\n"); > + return -ENOMEM; > + } > + > + dev->stats.tx_bytes += skb->len; > + break; > + > + default: > + dev->stats.tx_dropped++; > + dev_kfree_skb(skb); > + return -ENOMEM; > + } > + > + pr_info("Tx data skb->len:%d ", skb->len); > + send_buf = (u8 *)skb->data; > + pr_info("\nTransmitted data:\n"); > + for (i = 0; i < 16; i++) { > + if (i == skb->len) > + pr_info("++++"); > + else > + pr_info("%02x\n", send_buf[i]); > + } > + spin_lock_irqsave(&priv->lock, flags); > + > + /* Start from the next BD that should be filled */ > + bd = priv->curtx_bd; > + bd_status = ioread16be(&bd->status); > + /* Save the skb pointer so we can free it later */ > + priv->tx_skbuff[priv->skb_curtx] = skb; > + > + /* Update the current skb pointer (wrapping if this was the last) */ > + priv->skb_curtx = > +     (priv->skb_curtx + 1) & TX_RING_MOD_MASK(TX_BD_RING_LEN); > + > + /* copy skb data to tx buffer for sdma processing */ > + memcpy(priv->tx_buffer + (be32_to_cpu(bd->buf) - priv->dma_tx_addr), > +        skb->data, skb->len); > + > + /* set bd status and length */ > + bd_status = (bd_status & T_W_S) | T_R_S | T_I_S | T_L_S | T_TC_S; > + > + iowrite16be(bd_status, &bd->status); > + iowrite16be(skb->len, &bd->length); Should not status write be after length as status write will trigger the transmit? Also, RX/TX error handling is very basic. There is only RX/TX errors but no detail such as overrun/frame, carrier, crc etc.  These are very useful when trying to find the cause of an RX/TX error, especially during devlopment.  Jocke