From patchwork Wed Mar 15 20:11:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Lendacky X-Patchwork-Id: 739421 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 3vk2nF6wRSz9ryr for ; Thu, 16 Mar 2017 07:11:45 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="FWua9dLY"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753876AbdCOULn (ORCPT ); Wed, 15 Mar 2017 16:11:43 -0400 Received: from mail-sn1nam01on0085.outbound.protection.outlook.com ([104.47.32.85]:48872 "EHLO NAM01-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753635AbdCOUL1 (ORCPT ); Wed, 15 Mar 2017 16:11:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=HB8SxsZaTmKVZuQb+0OEoJGcRIAVa9JUWP0ZwLhCyiQ=; b=FWua9dLYTOTwdWFRbZDmp/Ao1i3Fn4fJrTFON+tTkD6xDMnnUF8/qAF9M1tL6N6ar2BYvuUUl/R/qVDWyyXZcfONSHsp0eRtXfWOotwBAmXVcNAowGEt35CjzlaAnpGuk8PjMxQCTfBIAyH2tX5Hc6EG/jNSI972vhEps29RITg= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=amd.com; Received: from tlendack-t1.amdoffice.net (165.204.77.1) by CY4PR12MB1142.namprd12.prod.outlook.com (10.168.163.150) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.961.17; Wed, 15 Mar 2017 20:11:25 +0000 From: Tom Lendacky Subject: [PATCH net] amd-xgbe: Fix jumbo MTU processing on newer hardware To: CC: David Miller Date: Wed, 15 Mar 2017 15:11:23 -0500 Message-ID: <20170315201123.12279.98988.stgit@tlendack-t1.amdoffice.net> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: CY4PR19CA0034.namprd19.prod.outlook.com (10.172.173.148) To CY4PR12MB1142.namprd12.prod.outlook.com (10.168.163.150) X-MS-Office365-Filtering-Correlation-Id: 81e95bdd-f312-4ad8-4da5-08d46bdf756f X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081); SRVR:CY4PR12MB1142; X-Microsoft-Exchange-Diagnostics: 1; CY4PR12MB1142; 3:IYrZKaGMakkBUTpxectSeS/PUiHSWH/rnnl+uw4yC8ERioN7OzsgdZin/BmMocc/AgXc1dEW3AbdFBUW8dxyu+rzc2rqqaPZ95OH64EQetLIiPmUN9+7OjeLbjmX0QJZS0Ys2X0NFeo8pkAXRYJbD9fUwGmO0PaP1ZsalVQ+3eFKWs4gv9TYlWOM2p+JzNmj1ae5Kz83l4PWfxgN/8KYYMowO8NPGxvCG9xIsdAlTBcWH2XTj4M6n7xVQs2IzQauqrqi9rFwiXSzzS/GICB7u9XpCFUok8eGGtFKLcOUqSw=; 25:PODHu0Oidr1pQEK9yRwne2BUNpWhG1PF+p664IHWX3lpY4wAnzG3s9jjEJ6WHV/d4AAVub83WRt3HabOiHuSvbvPzP4KNZufnZcvYtdSCvUGfyRpKLfE5GJ6I0MveUEcfyIu+R7rPH3ssipVKOyQi2jn0Th8iN0AK3MtfITCp8QnoZ083E5F88P0A4tTyFUx/E+HEX8EaIBFhCycPOR+9c044hcLBgOgFPnhnNLgQdKWrCvfkwUerGfQbSmWrnE8uXFn0d73EOcLc5+ua5iKuN5Z2reGfVND0YgIdLw23Z19fLEshk+XVkL64mVLzZLUIyc9VQyhk6Z066BajU50HNu8i5VcHXbV2i0OQ+oaMTiOk+jmFZalKthhwmBfneBxUIDYL6dldOyh6bPrQ8bLxyMHAuBjUvsgBvblNIdOoWzSR8WjiUPNE3MRrpBq2TEgKEJy44ceqy5b4NMWgl+ocg== X-Microsoft-Exchange-Diagnostics: 1; CY4PR12MB1142; 31:VwA6qDXpbr4VagCqE+QwDErzAecNpKsVLLyDK/2rMG1C0i9pIUUCkjVsWb/G1TLqv4/4tCCzwGB53xVOFHQFNIEFuSeuvcy/jCyRuQdKnkK9mYHpfLCcTVMWcFyGppzH/61yHBCFo/T5tztj7ztE+ShfWjlUja5vXg/lNYLm1w9CBVj0ItYVcyDgaFf0jVYNY52xeCp62jfzvOlAALGRzfOIC5TRN/2+Ta7Z3t5dY6s=; 20:yblp2EOL8H+3TVQGTU1gzp37YN2sT5xFRIklK9N88+JOfyxlAzh0MDwumEO30hnp3XYvgyL6bnBNQDyAMZCf+C3XCCPpThDN80Bwp0c/Ctk54Rf19lCkTLywA0k/6Lw7Yg0x9bxmnUT+rMlcMtaRr7oj4qtpY02Pcqc/9ycPoWCOba0WdfPpMUNEZ6n576hfgGVMaEZxdHTHQyrkNPAtsbADJtwbYxPvtQLEDqHcZU+fM3uL9Lp9DWeIHckke6izvDzDyvJQBV6UoPkrQxVJUdW4axPnVISPng4C8CmnFW+jZQftmjPhAr8mIqr6UNhDSnvlZNmgfgy7mSRXYVB3LpCnRrZhfOpKgDWQMQMzQwlDYXUHBVz+GoDrzDM5axKw0rZLZFB9N7wuTWOwBdnQpIFNhJDpoH0j6pY/owyrek3j4Twu9AxOASuGc/06S65jvwtn6ZumLNr4XjLmkZd2qjtBRw6btXBdt+7yShWrHnZ7fEDNm0iNCFnilblVEvKI X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6055026)(6041248)(20161123555025)(20161123562025)(20161123560025)(20161123564025)(20161123558025)(6072148); SRVR:CY4PR12MB1142; BCL:0; PCL:0; RULEID:; SRVR:CY4PR12MB1142; X-Microsoft-Exchange-Diagnostics: 1; CY4PR12MB1142; 4:qqHZkgXD7d5Tf+m5Jk7IvXXGAMO8VRwfXVWsW6UoIPRNrQoNtzHWLG2H8WEigvziKRvxbvu6cRkIp7i7RO4zccbEmSc4oIr/eyi4RjaXskjK2r9I9ddBHx9DrKXVFYlUE9AmjRTlCAcFOSxPm8zFTiFuQpwX62RHkJQSW2IzDJODCz7C2vSA0GxIL3xx9TB+PN2/FMF3uKZSwwGZnB6ky43WPy+JjcdKTxSg8RHRqIf+BR8QJWpZa11HnM3/DpHe2OL1d28EK9+BjwXMAih+6iR6clqPnocUWJ8U0i9TjCFLyFD5N+pNBfwGJqbiA5Z/TNTsBSMT8HZ27BoQ2sV64oufXbZISgvlqjAs/gqlX8xCIA3qjdfQmmRCqMMvQoxElEaf6FkkS3NElqTLWhKVXRDz1PRFGIGm/cB5Me6U86+p0WLLENq5LdyK6khUlVDby1BzOEV7Z15dpmeNYEfEzt1YBgXE6g5EcgCe3ojI45s5dCfbE9uS0gnGT4FTKSPvMokcKmphizbQXLbmlk3xrYPt9J3z52qUaQuq8ThqZYIomOPslgWmu4o7FvKdS6B3UI1FrfxOesyWHkVFtQCa3thG5MzSLP2vjmAZGkX8+Z9JB5eBTic8PxCpDqQFujV7YxZ00FIguEv3Om0tuW6TyRo6gT01nGSggxsHdhvzFT8= X-Forefront-PRVS: 02475B2A01 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(39850400002)(39410400002)(39450400003)(39860400002)(42186005)(110136004)(2351001)(66066001)(53416004)(103116003)(189998001)(6116002)(47776003)(23676002)(7736002)(8676002)(81166006)(3846002)(230700001)(4001350100001)(305945005)(5660300001)(38730400002)(6506006)(6916009)(97746001)(4326008)(1076002)(33646002)(2906002)(54356999)(86362001)(50466002)(9686003)(55016002)(25786008)(53936002)(50986999)(83506001)(71626007); DIR:OUT; SFP:1101; SCL:1; SRVR:CY4PR12MB1142; H:tlendack-t1.amdoffice.net; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtDWTRQUjEyTUIxMTQyOzIzOko2QlpSTGlTNTYyamo3MVUwN0N4L0l0d2RS?= =?utf-8?B?L2RnRExLRGVWaVZaamE3YmdycmNsWVdYOW11VXc0WTBHamRQV0JpT2NaNlY3?= =?utf-8?B?amNkRVJ6ZHZXcFNkTXliZEJITllHbkwwRkdGc0NhZjdPemx4V2ZTTFQ0R0NL?= =?utf-8?B?U0cwb2REOE9DQktobGZXWjRSc1NYVWFlL1lOUGtzQzRPc2RkZHBBdGlpQXRV?= =?utf-8?B?dUtyT2RJaEtsZzNIM1lFUm1CdXk4bThyTDNIWjM3VVhHeEpyODdjU1hJVmZ6?= =?utf-8?B?VXNkZ1RCTWVFMGZodEdBSVg0M1pld3RqbjQzcUNCZXIzSitIVkJrZjZBVXli?= =?utf-8?B?SmZVWlAxVWlRQTlYTldxSG5XUCt1YVQxMktsM2pWeEU2TWtERmEyRnJPV0tQ?= =?utf-8?B?aFpZUTc1YkZoQnZxVkhMa2VHMFBxRGtBeUt0SVpZcUQ2Z2lBa2d6aU5sVDkr?= =?utf-8?B?aldZMk9seFZxbGNTcG5yRG5QNnQrSkZzakNBbGNaeVVndHl2SkxhZjNqa0Ry?= =?utf-8?B?Z21meWhaNEpYWDgvSTBKL1ZjQi83MGpvV1F1NE5QQld5QlFjMVQ1TktLUjJq?= =?utf-8?B?YW5BNDZaNEwwRzRTZW1IODNUK1V1SFFqbktjYU5lT25RQzd4VkNOaGFEYnVN?= =?utf-8?B?RjZ5OFRiM3R3dHM5WFlSSzdUZGR4bldWTGl2ZXFtRlQ2eEFuRk1xKzBrRzBx?= =?utf-8?B?UWVSTFdNTjE5NCtLU1RrU2VXTEU0d25RbVBwVldmSlRGbzBFMGNIRGFSS2xx?= =?utf-8?B?Nnk5MjVTVGlrcEQyLzNHdDRWYWp3WHY4aVBabFQ1enFRTzFpWFk5WnRNY1Rw?= =?utf-8?B?QVlLRkVXbG5ZRnI5L2E1S0ZBci8zcGcrNWdzazVyZFFicWZXektHaFlwdXNV?= =?utf-8?B?YW9EK25aeUdtNFIrNnFiWkljdmZlT1FFOXRGclJhZFQvSXJQWXdpayt2VVBF?= =?utf-8?B?dVE1cko2eXBjYUZySklqREtsTmxlVitzaGd3YUloZHhVTjF5WmF4MUI4MldU?= =?utf-8?B?R1NaSkRhWVBkR0sxNUdFbUxzR3lZd2FBZDBYSng1QUxUb2xBSncxemhFcFh2?= =?utf-8?B?M1ppeGdMOXAzYWNiajlJaVdtMnJZSTlmb0FHYlNoZ055U3BndzZST2sySmk2?= =?utf-8?B?MTR5c05vRDhqRmluS054eXVLOEJsc3kwK01YNWxCajkxRmRyQUMvOGZ2RlQx?= =?utf-8?B?NlJiUUtzM25Vb0ViK3NFMXFta1V5NWl5TzlzRC9TaW1YdTBiaW5wTUgxMDdO?= =?utf-8?B?RjY2UkVXU2ptY2JNZDV6Si83ZWlRQ0x0TW9JMW5KTEpZTS9jUytSUnBXSjlP?= =?utf-8?B?emdiMmZGdi9velBxYll6aVc3aXFLZ0tMUG1JVXVKU25LSjFHVnl0YXhjN09Q?= =?utf-8?B?MGhnK3doNGFXbGxTY25BZWRtMDZSUmdweW9FVFI2ODBja3gvOTBBRUhGZVRB?= =?utf-8?Q?/+ltqI=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR12MB1142; 6:FkJb1WdsCi9hToJNrcJwxJaEYSqMelG6Tgd7b/98DJ3KndpItKRd5xN08bWevRjOxWCr2xVN+cU78iZ/fq7Cn1B2uBqxe6xkLrrD/JqyRwcN2FHkVUyIizVtOepzcRnG3p2VU/q55GZtrzxx+DWOlw3VSEiM4Ub/E3frHN0B7XYmWDPq0YCxU4HedAS5JLHkPvQoyS0Mpa+fyZ33i1hIFG4OEZ9Q3zJCEd1PMYw2EaCm4WA5N3KC52CQfE74sMGsFPq63PG0AHvSxdjk49fyfBmFuF5WlpuQ3bvNsHltuqsq2dYXp3FFaozRiWdkssWwmEh+lAiHTTMVOCUzHHyw2vkRXQqldBtiEbAmI3crsp0t7Yll1WhXreMqifQ5eA1Rg+AaSNABkzLKp+k/3Sd3Ap8cW9nk1PDmumzHxc+WOnY=; 5:7uh9e1D5Jqfr2/iCIaSZnmaF3Udabmi6jvvgFuffwPC+Gq9z1IeldTUyOen38pGDBRa6J2J+gCoC4XMY1S8lik00ZrRQlt2VXncx2Emzx0Gl8bY1p8E9ZjjgSXEh4RZrT4Gq8Yscx3LKXv4BlqoURg==; 24:erQuHSe+fb0t8Y1jA26xN8qfwm1TnVUWV4tWmooDtfbTcmIKmUl9QcnkJOFyBRsxcdM0Kx8pD1u2A8GW9kVyykh8apiILzmvu4F7m7ah6yc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY4PR12MB1142; 7:oH9lS557xHQ61DLaVABrFpYyjtbAicZ0zkFPzzDjX4UzAsVfBxz+ngTO4YsA+5k711lGcS23RS/SqUL0xfNe6W1Oi00XCuX9yAtXPadv8tS5FFplgO5g3+Bu7OneMOabeFBNTGEw12UlYnsdPIA1PN3EGpu0zNgxJmuwxdXaKpRD6bOcRtqqp64AgHgNa/och+0jqqWlNHnFSBJtp3fv/PBH0OSWvKVK0J9WsHMmy9VzMWekZzdvhyQGXbZ8HHSpa/u7OfK/Mf8ySj9B7T36KyclIZWmiJ7kmyXw50RXFjZpE2RRCftr61ZGiUNUouoq9VUkwHihkruGnHHOpsyfBg==; 20:w0xIN+PZAmuZzl0litMMF/K5fN/r/105WP0lA5+HsjrtcEeoMkqUC3pAioiDidca9UM4Y+o9TAEdqhpufrv3mwlo1/VTR8KkDO6XRkUISJSjCm4wKSCF1oy+yvJbyGjEXYNYuP4lLwehZqziki54U/ze/PMlGeZRDKUZftpwf6JzyqZYNjkhhVQebab49q6Ce5oWq8V2F94Sc7NRxyXqybPIf9rzYZQ8nONQrSbq/RAXE2chJ64pgJ0ya4G6mtLw X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Mar 2017 20:11:25.6438 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR12MB1142 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Newer hardware does not provide a cumulative payload length when multiple descriptors are needed to handle the data. Once the MTU increases beyond the size that can be handled by a single descriptor, the SKB does not get built properly by the driver. The driver will now calculate the size of the data buffers used by the hardware. The first buffer of the first descriptor is for packet headers or packet headers and data when the headers can't be split. Subsequent descriptors in a multi-descriptor chain will not use the first buffer. The second buffer is used by all the descriptors in the chain for payload data. Based on whether the driver is processing the first, intermediate, or last descriptor it can calculate the buffer usage and build the SKB properly. Tested and verified on both old and new hardware. Signed-off-by: Tom Lendacky --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 6 +- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 20 +++-- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 102 +++++++++++++++++---------- 3 files changed, 78 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 8a280e7..86f1626 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -1148,8 +1148,8 @@ #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_LAST_INDEX 2 +#define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 @@ -1158,6 +1158,8 @@ #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7 +#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1 #define RX_NORMAL_DESC0_OVT_INDEX 0 #define RX_NORMAL_DESC0_OVT_WIDTH 16 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 937f37a..24a687c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel) /* Get the header length */ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + FIRST, 1); rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, HL); if (rdata->rx.hdr_len) pdata->ext_stats.rx_split_header_packets++; + } else { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + FIRST, 0); } /* Get the RSS hash */ @@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel) } } - /* Get the packet length */ - rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); - - if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { - /* Not all the data has been transferred for this packet */ - XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - INCOMPLETE, 1); + /* Not all the data has been transferred for this packet */ + if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) return 0; - } /* This is the last of the data for this packet */ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - INCOMPLETE, 0); + LAST, 1); + + /* Get the packet length */ + rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); /* Set checksum done indicator as appropriate */ if (netdev->features & NETIF_F_RXCSUM) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index ffea985..a713abd 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1971,13 +1971,12 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, { struct sk_buff *skb; u8 *packet; - unsigned int copy_len; skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); if (!skb) return NULL; - /* Start with the header buffer which may contain just the header + /* Pull in the header buffer which may contain just the header * or the header plus data */ dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, @@ -1986,30 +1985,49 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, packet = page_address(rdata->rx.hdr.pa.pages) + rdata->rx.hdr.pa.pages_offset; - copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len; - copy_len = min(rdata->rx.hdr.dma_len, copy_len); - skb_copy_to_linear_data(skb, packet, copy_len); - skb_put(skb, copy_len); - - len -= copy_len; - if (len) { - /* Add the remaining data as a frag */ - dma_sync_single_range_for_cpu(pdata->dev, - rdata->rx.buf.dma_base, - rdata->rx.buf.dma_off, - rdata->rx.buf.dma_len, - DMA_FROM_DEVICE); - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - rdata->rx.buf.pa.pages, - rdata->rx.buf.pa.pages_offset, - len, rdata->rx.buf.dma_len); - rdata->rx.buf.pa.pages = NULL; - } + skb_copy_to_linear_data(skb, packet, len); + skb_put(skb, len); return skb; } +static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata, + struct xgbe_packet_data *packet) +{ + /* Always zero if not the first descriptor */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST)) + return 0; + + /* First descriptor with split header, return header length */ + if (rdata->rx.hdr_len) + return rdata->rx.hdr_len; + + /* First descriptor but not the last descriptor and no split header, + * so the full buffer was used + */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) + return rdata->rx.hdr.dma_len; + + /* First descriptor and last descriptor and no split header, so + * calculate how much of the buffer was used + */ + return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len); +} + +static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata, + struct xgbe_packet_data *packet, + unsigned int len) +{ + /* Always the full buffer if not the last descriptor */ + if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) + return rdata->rx.buf.dma_len; + + /* Last descriptor so calculate how much of the buffer was used + * for the last bit of data + */ + return rdata->rx.len - len; +} + static int xgbe_tx_poll(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; @@ -2092,8 +2110,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) struct napi_struct *napi; struct sk_buff *skb; struct skb_shared_hwtstamps *hwtstamps; - unsigned int incomplete, error, context_next, context; - unsigned int len, rdesc_len, max_len; + unsigned int last, error, context_next, context; + unsigned int len, buf1_len, buf2_len, max_len; unsigned int received = 0; int packet_count = 0; @@ -2103,7 +2121,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) if (!ring) return 0; - incomplete = 0; + last = 0; context_next = 0; napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; @@ -2137,9 +2155,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) received++; ring->cur++; - incomplete = XGMAC_GET_BITS(packet->attributes, - RX_PACKET_ATTRIBUTES, - INCOMPLETE); + last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + LAST); context_next = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT_NEXT); @@ -2148,7 +2165,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) CONTEXT); /* Earlier error, just drain the remaining data */ - if ((incomplete || context_next) && error) + if ((!last || context_next) && error) goto read_again; if (error || packet->errors) { @@ -2160,16 +2177,22 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) } if (!context) { - /* Length is cumulative, get this descriptor's length */ - rdesc_len = rdata->rx.len - len; - len += rdesc_len; + /* Get the data length in the descriptor buffers */ + buf1_len = xgbe_rx_buf1_len(rdata, packet); + len += buf1_len; + buf2_len = xgbe_rx_buf2_len(rdata, packet, len); + len += buf2_len; - if (rdesc_len && !skb) { + if (!skb) { skb = xgbe_create_skb(pdata, napi, rdata, - rdesc_len); - if (!skb) + buf1_len); + if (!skb) { error = 1; - } else if (rdesc_len) { + goto skip_data; + } + } + + if (buf2_len) { dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.buf.dma_base, rdata->rx.buf.dma_off, @@ -2179,13 +2202,14 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rdata->rx.buf.pa.pages, rdata->rx.buf.pa.pages_offset, - rdesc_len, + buf2_len, rdata->rx.buf.dma_len); rdata->rx.buf.pa.pages = NULL; } } - if (incomplete || context_next) +skip_data: + if (!last || context_next) goto read_again; if (!skb) @@ -2243,7 +2267,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) } /* Check if we need to save state before leaving */ - if (received && (incomplete || context_next)) { + if (received && (!last || context_next)) { rdata = XGBE_GET_DESC_DATA(ring, ring->cur); rdata->state_saved = 1; rdata->state.skb = skb;