From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756993AbdADHLD (ORCPT ); Wed, 4 Jan 2017 02:11:03 -0500 Received: from mail-sn1nam02on0065.outbound.protection.outlook.com ([104.47.36.65]:49429 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751148AbdADHKz (ORCPT ); Wed, 4 Jan 2017 02:10:55 -0500 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; From: Kedareswara rao Appana To: , , , , , , , , , , CC: , , , Subject: [PATCH v3 2/3] dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in vdma Date: Wed, 4 Jan 2017 12:24:06 +0530 Message-ID: <1483512847-25710-3-git-send-email-appanad@xilinx.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1483512847-25710-1-git-send-email-appanad@xilinx.com> References: <1483512847-25710-1-git-send-email-appanad@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-22800.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.100;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(7916002)(39450400003)(39860400002)(39850400002)(39410400002)(39840400002)(2980300002)(438002)(189002)(199003)(38730400001)(5660300001)(54906002)(2906002)(4326007)(47776003)(90966002)(42186005)(92566002)(48376002)(5003940100001)(81166006)(626004)(106466001)(45336002)(33646002)(46386002)(8936002)(7416002)(50226002)(2950100002)(103686003)(6666003)(36756003)(81156014)(8676002)(5001770100001)(356003)(50986999)(305945005)(2201001)(50466002)(36386004)(52956003)(63266004)(189998001)(76176999)(921003)(107986001)(5001870100001)(2101003)(83996005)(1121003);DIR:OUT;SFP:1101;SCL:1;SRVR:DM5PR02MB2778;H:xsj-pvapsmtpgw02;FPR:;SPF:Pass;PTR:xapps1.xilinx.com,unknown-60-100.xilinx.com;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2NAM02FT027;1:+EyuUbTLgxD6DPPYSJcxmrSZKPEfShfbwg9BRwJNaLcWD874Tcr2C4H350lzXJn9ilkEbB6NzWdQPO4c55MlwKvJqFWc+v+B4IGsB9Lxq/c6F9xvDFFy+SEKqt5uHAqOLeFEKyJpZ/5j25SUHLflVAu6VWZA3asqdr0UyZv4FoYr6XUVvxHE2k9BE9w8iZ7wZhFQHOlMu6mBmzhgHxp8UHFxzAZ4IXWJrMwnHJzb/P6M/UBUiY4TJ+GWDDlomThxn/UVc/5q6OBtfdzk8ajU5xwlECDgktBlyqn5qL89aEPREsJLQwXMDf9w9fus4buWwJ24SwMAaiXB4FX1wJc8v4GcZrpDirUi3Encycy9vVBcBCj4iZIKoq2I8RcDsWw/o/Z5YB+4F/GKXOtPlaYmCytvYcIwMPDIY0vwhL2E3GcM406rVczkWzoCEpyq0hK68fP/T4MqXH+QzTQJprNlYo+1MIzMEd1ZMR13s9U30PLN/YgskjtmCDv7Re8B5ofq68vUBkzji5znLLEFDxXGUXAzMFyOfGkDCKUvz8KJv22j/rUgysfaaq4CBtbMgnWu3h5GAVjXL1ll/PjVscItV4xmXB2Ea+S5IdKVtZs9tB4OKcXdJLcEVC7GqqKYrz2idrvP7PNDvihLndihNbQQIw== MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 1c2d7ddd-73c1-4f64-0480-08d4346e818f X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(8251501002);SRVR:DM5PR02MB2778; X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB2778;3:Kdgss8TQw2iI7ygJx8l5Efp3Ads2k/cuNMnxVKkZKA28YzMRpIh8NhYE7xpg09jlEW+emgQlFnTtJed4q5zffQIy7TTIBLL1Pye0NjiCte0f6YG5vDeby0cNfvkdpbWy0yJ6RubHxYbFwrnBn1UTMYJcudDsfb+aVUlY3KrrHiJ4nq++RurEp2pUaC1X53uH454ZIR1ja5RVD6TSBTW2wAykCGMACRvLyTGtAocRSUN5BG6Wwz1gYGOqrw8fTBjIKfZLjRWOyYue7pmbeR7y/0RMhui1bOVIBjOanlb8ewAEeltDifZWtP69XbeH0OJ18v/eE55Pbhr6CquTqXyxVcPaoui4hXQzAR0md7qa2/CqTr28M2rvZmZ8RmKr7PH1NPIGX6IysPtIFrchKfcisw==;25:roIfAbX4d1WbITvQgEV3IgP2y/pKekdj3d8Wnmx21Rsq+zLnm2AnAtMMd9HGAV1g7wAiV7oMLCHeHBxy2Z/MZgulHLXNC4mN/Gavkr8dGCpnL+6xNmglpCuw0QAm5tzUTbPipe3f6hobnBw9hhx/F/O0J9Dc/dCcXS2DDM+ezfepcduCVi30SftGhCtLNPsBsLLtDFJi6NW5OxmKE2RRfg4qaDgAtLq3szVOzA7ZdBGiE8SJt/kDFpjftmI+ZO6jDmc//+5Puiz1SABsFR+TNUXUu5iefrhprT2B3MHmt3lvq+tXezdHl9RSYEZksvosgHkNjStluh41aXoBOJxLP+Voz44Rn5KRw/xoiJA5TitV6oKKeYXgkjP/2VfoECSWKCi9xd5eog3VntS26w8C0f2jrtUo3At6Kch66tLoANzIlmU2NxrqEYowEUj3VDRUTKdbJbiordaWGtd3Svl1xw== X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB2778;31:wddUF7qE4ATPmL6wXRSQqhSjTBbfLrj9ECP8tCTKa9/RBELZq5DEqUovRCWszxfP45CKY6PtkqDUcYFD2ZnyUFjojNPGwkignmws9Zo83F5XKfy/+V9YFJwyTydnwYY9pyqWH1Rc+m9h9gGJcXTp/NtYX8KvsdH6B+M4StZYJT4LUrtskCnsb2571wT19sGWNBjqmo64toySAxi5OQL1StW4MwQPajsjhtkfh2o4Al6ZyJ1tBgWRWlWjvAMOdPfVL77mKeKc9w0XlNo5eQkv0AxYSHf2hu7rM87GDpJmiko=;20:LFdkEW5t5OPbisNtzVxLW5KdPwlO2TBnwxpmR8eaZb9K+XuGKDh87DlKbNJQLGCp6KYdLjPbyNGSBebJXGT1r8Qkfzu6uTUzPRu2V1E9eaK+jQ7yRQ4N1Yktn9Z44RywqMs3/bl2IuXjsC7B8w3TiXBQQ6DBQurHJguwl3Sap2Xfg6UWHQAeNMKr58lbZycpsDY93AbgHcrK+znab86yzPGVpb2sNZqs4plCq8ysz2MSCbWODKs65aonFD7YyO0K286zoxYFV5+DVRV94ucQFwzVZUUi9zMZdY8J6p/K7iQ/Hyse7rxknTRQ0Zvi0O/qXgRo6MB1wGdCZTGo9vd/644oEsmiGL7ARQpK5llcTkqh/+hIE30idVxmRHtZG/5grcWOwkon8ILs77YMY76p9NJcEjENC4l1MnHPZ9OZ1+az701xMf66Lc2RiVYmI28f1IQwI5UZb9tZpeQCCf6kgiyCaksozmpMVpTVAEyo9Og9MBBLk+r6BXI5glPUnItF X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(13024025)(13023025)(13015025)(13017025)(13018025)(8121501046)(5005006)(3002001)(10201501046)(6055026)(6041248)(20161123564025)(20161123562025)(20161123555025)(20161123560025)(6072148);SRVR:DM5PR02MB2778;BCL:0;PCL:0;RULEID:;SRVR:DM5PR02MB2778; X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB2778;4:a5q8cEWOCaMH10NDRWKV8gbOlw8p/KSPGqngOb4GRgeX3cggcyVPcAtmwWqWk7ZwAoamqcmCYgyEB5KiRIVo0NZQ289H5HI05SAX4dQlc8gYxniA5qdN7EQWS12j7YzjpZTndPQQex9VKXDIVrjMSddqDaoLO91AzDSpMZyLwjy1WxLHLw97HVWxP8cm7fOq2hDyqmm0nNlUxMtNh6N+WiL3UxobynNllKmwnqLuUj0JVSdfMagJy8k9n1C1XXGt1dgu3JSHbPGM1Mqb96+YqKTrd+KUceCLaLj8DEmqib7AzLY/T2jUq5D3Dfng4ynUx2jnypB7UmuE35Snm7MvFihBaYJTNeNxdcepZgVkjlfdCCKNXyuVNgW5WTXAV1zwlHTBaL6EyHR7oGaNs+VIX7Rj86nqI4sngAlw5L7EFN8UcGZAPV+t9+2XN0sOJEb2PO2f0R0MoG3c+tyMCt7aZ/chCu9KjQeRYG3894vjPD1Bby3iVYA12Jo+1IGane66XYT+UXdHtNlfQlXxzIV16rwxO5Z2/Esl0jkFqScnzXi8MUmJvc8CoHsJk1IRiEWJbI5AaKmQKhh7eENO7Oytcv7AVpzIEdBDEoDvT1ZxJNz1a3LC5HOtpE0e6Y5L4wqMKrT1RC/AtNSSx0XenjS+q4dI6Qc/Ej7G5kuBHqAy9IpI79vheReb2+RsZKI6FjLFCirXBP8a1PnHyKN+HDXbQBo4kocGJzvbVTooixXziw4= X-Forefront-PRVS: 0177904E6B X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DM5PR02MB2778;23:AKRWT3rMuAXISNHVmsKlhCqMhj0jR5bf9c4DVBHLL?= =?us-ascii?Q?mrl2Nsx+UitQUCrIr17yFusm0xY5J6DFd5YjRZw6sKMxDjQBMUj9HnDPiC4e?= =?us-ascii?Q?iDRDvSaq/JLR/DCRjH5HDW3OXd2DQqnJYasuOSKbwiJU68ZvYkL/KWHiesus?= =?us-ascii?Q?QtpnMbUyf/Ksnez0bHrQm9yWNBYz0XEDm0Os+V3h9ukokox1hpXs65IVTTs7?= =?us-ascii?Q?duo3QMPUEsp77DvyEVt4KT3V6jYSictp6HaZzCCPM6oUkv9+i3VxJENc6N7O?= =?us-ascii?Q?C7e7EJ5rsaPbZlGrUKUE5Ex6lBUabmIfwPS89grhHwtOtZDPKB2mrzm7otfo?= =?us-ascii?Q?7BxrYdmvfKRhGp8+wdlIHmWwvxpsHemBy5oottZ3OJ3EEuY9oUGYkJSG8d3E?= =?us-ascii?Q?OXO6AhmQeUvJ/5I7gYXYUNVgWgGxHxsXR5FWrmN8PwPBrNYSVL7apRtKT0kd?= =?us-ascii?Q?wzp9dcb1Fp+Hvc1sqhDxCpOrG/4Sty4pp1rHTkRV49ULMc+r3exRgqrgHYjf?= =?us-ascii?Q?qq0vCa4tjNMPu0RikhmE8RyMWF21Po1kM2wvrG5bJsh8TGrf0b0+TeWS2x5e?= =?us-ascii?Q?NFuKwRcXaJkr8Cj0Q1Qo4zn1blzdi2AlRzeDVmKnv95yrX192i2S4u1ZQtdV?= =?us-ascii?Q?ISUzbxftC3Kgx2KND3tmC8ganz2jrtNyEUK837haJPGN8GAGOgPuhLfErrAQ?= =?us-ascii?Q?lr+1u3qGQDPwQgL+JbGa0TyZtqTpOObFvyD+YOLlSwAmEb4o5qa5+A6nm+vu?= =?us-ascii?Q?JX4FtZV8nJ4oKnvXg+4F4Uovx+lj9KDNF6yeK2sp1SKjnVLaAtec9itk5CMQ?= =?us-ascii?Q?92HrV7c6MhJHHYHLqIfw1LfkcA/JW9QZFcUVxcIIP6UF0a2Gr1vGjeOad0vP?= =?us-ascii?Q?evQlsVqBw/7it4R4lpMJjyoxnhHVtGnS7QYwkUOAJUmxDJGNpM78p8QHNKg5?= =?us-ascii?Q?nJiQIYP/37ojebu+yknnODuC6LsoJ9rU1KKnVeeFamVUB165yNy6Hl9IetZP?= =?us-ascii?Q?cBk1YLqxalEApvWxkDpBl/StPTNREFiuzo/Ri0UV5Y9KJ3K8U6p/Rz16UiqC?= =?us-ascii?Q?H3Kw3nJAvQKx/eQe8wt0XBDD92OKvmznU64PraXbHRQ+CIjBnwqh+dQkOr9X?= =?us-ascii?Q?gTGFRdEfGsIE/C0ZRz+4mpmRfK+Tu2u1DDEkQ500vCLDgSczb7TnKWILMxUK?= =?us-ascii?Q?1EQ6N6zmiQNv5l8CAL/2BdE8iITNmPizDYMPpO0fR2hH6xhHQ7BY+fvUWcg0?= =?us-ascii?Q?vw02WSJCNdL2riwrAMlNE/GFT6+jyQnp41T+V+EaWVIxCSmMG/6Dy+TsafcW?= =?us-ascii?Q?8G0a5hgEYPZzoCx867pMHQ=3D?= X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB2778;6:tupAnnP6fiBCykecoRGcQU4+9vVoUItS4ZQyTZ+A18/DVKwjV01vW3uiVDYuqBc/5wF11Bj6fYGyPS571mz0WCSs18l/GnznSEb/YTf6V/kATdz8JInmCr1Laer5zyaTgUjccYZz6IMmZdHlMkPKwHjPyca64hWA+mWLR2bpq2Jnf3g9hXjawURZ3B6aNnX3lqdJq36RlSNxrH9Lgj3toIxEbgHAqafUWU0uI3y9zWmW1oVAXDtWrNhCOsdZv6vc0pnoYqhxP57p6CXA8j/87bt6aiIe4lOWvcGmaY2IboUcdjSE3pcBLDryQZS9nCLjS1mV3lDXeJsjNSM5JsaC6FFJ+saOh47CAdpXhxT1q4g/4KVzMILDG8oA4XisqPGGg5Rx+FckoUBD3yehMXh34k2FeYeeHDBxhk0sMmshT963Fmgot6reRBYT0p2/KjOX9lieOD+ueNQcHIifkeQFWQ==;5:678mbi+0xwt4EfXhfp0fpvGUsoIaYGXTdiaRL8zO2HP+/2AW4YaEn9X9Y8plkeEUV7xILPqAfaX1BHM3M6ZEesu9mCa9Ps5GfjDvTcQg8ZOTnrN4veESTQF74w9INinthXWH527/Fil6zY8J/9f7/D0hJVWs3zYwaflJOVL612A=;24:bdhpNTeTwblDSaJs4TYE38SjNIMGx+3YqCzFelQdfvknxDVd2PNvUdzKCco+xlEmTbq8rlNIv+Ga0EHNLDUGE3HQxN0VO1X8YgvS7L+nQAA= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB2778;7:JjOmT3uK3H7DD7PLbZ9nyZig1lWYqZtalmwrpqnZz/NWkGTqjhY0SToCc7YHKnXI2jh/PG+d7Zl797/F0DTSsRvE/O5mGYpB5MWPbtHbgYk6hR05qpL+b+BNzTphVbb9l1ZzWaEnRp879uxlTR5//BepGSb7NrG4LSTZxVEYw4Q0KzVDNFi/YTvsf8zw1133nsVeiE+4NUFZciVNnqubdRAbkG/hKH3Xj8YCzfHPxqVS8L+SyUOtvhGaYCFhen9bFWSOelF2qAAtVcdHfqvQwsAJpZVnIsdfm43I6utqAfHuTIJrKq6HfLILR1BXXXgRtu7LroHvV7s+Z09C0Vk3QxAyh7WXctOdrUdNdMj0b7ezs+nXaHcPjA3ciY2+f8E2jwoQe3j412slXYWQtrhQukMKnGicX+0YjDeRt+Vqvnsh+WHnEx7lYM2Ul7I48XAsYqA2EZTcqtLtFtlAW5hgNA== X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Jan 2017 06:54:18.8106 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.100];Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR02MB2778 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When VDMA is configured for more than one frame in the h/w for example h/w is configured for n number of frames and user Submits n number of frames and triggered the DMA using issue_pending API. In the current driver flow we are submitting one frame at a time but we should submit all the n number of frames at one time as the h/w Is configured for n number of frames. This patch fixes this issue. Signed-off-by: Kedareswara rao Appana --- Changes for v3: ---> Added Checks for frame store configuration. If frame store Configuration is not present at the h/w level and user Submits less frames added debug prints in the driver as relevant. Changes for v2: ---> Fixed race conditions in the driver as suggested by Jose Abreu ---> Fixed unnecessray if else checks in the vdma_start_transfer as suggested by Laurent Pinchart. .../devicetree/bindings/dma/xilinx/xilinx_dma.txt | 2 + drivers/dma/xilinx/xilinx_dma.c | 78 +++++++++++++++------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt index a2b8bfa..1f65e09 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt @@ -66,6 +66,8 @@ Optional child node properties: Optional child node properties for VDMA: - xlnx,genlock-mode: Tells Genlock synchronization is enabled/disabled in hardware. +- xlnx,fstore-config: Tells Whether Frame Store Configuration is + enabled/disabled in hardware. Optional child node properties for AXI DMA: -dma-channels: Number of dma channels in child node. diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index be7eb41..7cd8e08 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -322,6 +322,7 @@ struct xilinx_dma_tx_descriptor { * @genlock: Support genlock mode * @err: Channel has errors * @idle: Check for channel idle + * @has_fstoreconfig: Check for frame store configuration * @tasklet: Cleanup work after irq * @config: Device configuration info * @flush_on_fsync: Flush on Frame sync @@ -353,6 +354,7 @@ struct xilinx_dma_chan { bool genlock; bool err; bool idle; + bool has_fstoreconfig; struct tasklet_struct tasklet; struct xilinx_vdma_config config; bool flush_on_fsync; @@ -990,6 +992,26 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (list_empty(&chan->pending_list)) return; + /* + * Note: When VDMA is built with default h/w configuration + * On the S2MM(recv) side user should submit frames upto + * H/W configured. If users submits less than h/w configured + * VDMA engine tries to write to a invalid location + * Results undefined behaviour/memory corruption. + * + * If user would like to submit frames less than h/w capable + * On S2MM side please enable debug info 13 at the h/w level + * It will allows the frame buffers numbers to be modified at runtime. + */ + if (!chan->has_fstoreconfig && chan->direction == DMA_DEV_TO_MEM && + chan->desc_pendingcount < chan->num_frms) { + dev_dbg(chan->dev, "Frame Store Configuration is not enabled at the"); + dev_dbg(chan->dev, " H/w level enable Debug info 13 at the h/w level"); + dev_dbg(chan->dev, " OR Submit the frames upto h/w Capable\n\r"); + + return; + } + desc = list_first_entry(&chan->pending_list, struct xilinx_dma_tx_descriptor, node); tail_desc = list_last_entry(&chan->pending_list, @@ -1052,25 +1074,38 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (chan->has_sg) { dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC, tail_segment->phys); + list_splice_tail_init(&chan->pending_list, &chan->active_list); + chan->desc_pendingcount = 0; } else { struct xilinx_vdma_tx_segment *segment, *last = NULL; - int i = 0; + int i = 0, j = 0; if (chan->desc_submitcount < chan->num_frms) i = chan->desc_submitcount; - list_for_each_entry(segment, &desc->segments, node) { - if (chan->ext_addr) - vdma_desc_write_64(chan, - XILINX_VDMA_REG_START_ADDRESS_64(i++), - segment->hw.buf_addr, - segment->hw.buf_addr_msb); - else - vdma_desc_write(chan, - XILINX_VDMA_REG_START_ADDRESS(i++), - segment->hw.buf_addr); - - last = segment; + for (j = 0; j < chan->num_frms; ) { + list_for_each_entry(segment, &desc->segments, node) { + if (chan->ext_addr) + vdma_desc_write_64(chan, + XILINX_VDMA_REG_START_ADDRESS_64(i++), + segment->hw.buf_addr, + segment->hw.buf_addr_msb); + else + vdma_desc_write(chan, + XILINX_VDMA_REG_START_ADDRESS(i++), + segment->hw.buf_addr); + + last = segment; + } + list_del(&desc->node); + list_add_tail(&desc->node, &chan->active_list); + j++; + if (list_empty(&chan->pending_list) || + (i == chan->num_frms)) + break; + desc = list_first_entry(&chan->pending_list, + struct xilinx_dma_tx_descriptor, + node); } if (!last) @@ -1081,20 +1116,14 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE, last->hw.stride); vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize); - } - chan->idle = false; - if (!chan->has_sg) { - list_del(&desc->node); - list_add_tail(&desc->node, &chan->active_list); - chan->desc_submitcount++; - chan->desc_pendingcount--; + chan->desc_submitcount += j; + chan->desc_pendingcount -= j; if (chan->desc_submitcount == chan->num_frms) chan->desc_submitcount = 0; - } else { - list_splice_tail_init(&chan->pending_list, &chan->active_list); - chan->desc_pendingcount = 0; } + + chan->idle = false; } /** @@ -1342,6 +1371,7 @@ static int xilinx_dma_reset(struct xilinx_dma_chan *chan) chan->err = false; chan->idle = true; + chan->desc_submitcount = 0; return err; } @@ -2315,6 +2345,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, has_dre = of_property_read_bool(node, "xlnx,include-dre"); chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode"); + chan->has_fstoreconfig = of_property_read_bool(node, + "xlnx,fstore-config"); err = of_property_read_u32(node, "xlnx,datawidth", &value); if (err) { -- 2.1.2 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kedareswara rao Appana Subject: [PATCH v3 2/3] dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in vdma Date: Wed, 4 Jan 2017 12:24:06 +0530 Message-ID: <1483512847-25710-3-git-send-email-appanad@xilinx.com> References: <1483512847-25710-1-git-send-email-appanad@xilinx.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1483512847-25710-1-git-send-email-appanad@xilinx.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: robh+dt@kernel.org, mark.rutland@arm.com, dan.j.williams@intel.com, vinod.koul@intel.com, michal.simek@xilinx.com, soren.brinkmann@xilinx.com, appanad@xilinx.com, moritz.fischer@ettus.com, laurent.pinchart@ideasonboard.com, luis@debethencourt.com, Jose.Abreu@synopsys.com Cc: dmaengine@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org When VDMA is configured for more than one frame in the h/w for example h/w is configured for n number of frames and user Submits n number of frames and triggered the DMA using issue_pending API. In the current driver flow we are submitting one frame at a time but we should submit all the n number of frames at one time as the h/w Is configured for n number of frames. This patch fixes this issue. Signed-off-by: Kedareswara rao Appana --- Changes for v3: ---> Added Checks for frame store configuration. If frame store Configuration is not present at the h/w level and user Submits less frames added debug prints in the driver as relevant. Changes for v2: ---> Fixed race conditions in the driver as suggested by Jose Abreu ---> Fixed unnecessray if else checks in the vdma_start_transfer as suggested by Laurent Pinchart. .../devicetree/bindings/dma/xilinx/xilinx_dma.txt | 2 + drivers/dma/xilinx/xilinx_dma.c | 78 +++++++++++++++------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt index a2b8bfa..1f65e09 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt @@ -66,6 +66,8 @@ Optional child node properties: Optional child node properties for VDMA: - xlnx,genlock-mode: Tells Genlock synchronization is enabled/disabled in hardware. +- xlnx,fstore-config: Tells Whether Frame Store Configuration is + enabled/disabled in hardware. Optional child node properties for AXI DMA: -dma-channels: Number of dma channels in child node. diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index be7eb41..7cd8e08 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -322,6 +322,7 @@ struct xilinx_dma_tx_descriptor { * @genlock: Support genlock mode * @err: Channel has errors * @idle: Check for channel idle + * @has_fstoreconfig: Check for frame store configuration * @tasklet: Cleanup work after irq * @config: Device configuration info * @flush_on_fsync: Flush on Frame sync @@ -353,6 +354,7 @@ struct xilinx_dma_chan { bool genlock; bool err; bool idle; + bool has_fstoreconfig; struct tasklet_struct tasklet; struct xilinx_vdma_config config; bool flush_on_fsync; @@ -990,6 +992,26 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (list_empty(&chan->pending_list)) return; + /* + * Note: When VDMA is built with default h/w configuration + * On the S2MM(recv) side user should submit frames upto + * H/W configured. If users submits less than h/w configured + * VDMA engine tries to write to a invalid location + * Results undefined behaviour/memory corruption. + * + * If user would like to submit frames less than h/w capable + * On S2MM side please enable debug info 13 at the h/w level + * It will allows the frame buffers numbers to be modified at runtime. + */ + if (!chan->has_fstoreconfig && chan->direction == DMA_DEV_TO_MEM && + chan->desc_pendingcount < chan->num_frms) { + dev_dbg(chan->dev, "Frame Store Configuration is not enabled at the"); + dev_dbg(chan->dev, " H/w level enable Debug info 13 at the h/w level"); + dev_dbg(chan->dev, " OR Submit the frames upto h/w Capable\n\r"); + + return; + } + desc = list_first_entry(&chan->pending_list, struct xilinx_dma_tx_descriptor, node); tail_desc = list_last_entry(&chan->pending_list, @@ -1052,25 +1074,38 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (chan->has_sg) { dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC, tail_segment->phys); + list_splice_tail_init(&chan->pending_list, &chan->active_list); + chan->desc_pendingcount = 0; } else { struct xilinx_vdma_tx_segment *segment, *last = NULL; - int i = 0; + int i = 0, j = 0; if (chan->desc_submitcount < chan->num_frms) i = chan->desc_submitcount; - list_for_each_entry(segment, &desc->segments, node) { - if (chan->ext_addr) - vdma_desc_write_64(chan, - XILINX_VDMA_REG_START_ADDRESS_64(i++), - segment->hw.buf_addr, - segment->hw.buf_addr_msb); - else - vdma_desc_write(chan, - XILINX_VDMA_REG_START_ADDRESS(i++), - segment->hw.buf_addr); - - last = segment; + for (j = 0; j < chan->num_frms; ) { + list_for_each_entry(segment, &desc->segments, node) { + if (chan->ext_addr) + vdma_desc_write_64(chan, + XILINX_VDMA_REG_START_ADDRESS_64(i++), + segment->hw.buf_addr, + segment->hw.buf_addr_msb); + else + vdma_desc_write(chan, + XILINX_VDMA_REG_START_ADDRESS(i++), + segment->hw.buf_addr); + + last = segment; + } + list_del(&desc->node); + list_add_tail(&desc->node, &chan->active_list); + j++; + if (list_empty(&chan->pending_list) || + (i == chan->num_frms)) + break; + desc = list_first_entry(&chan->pending_list, + struct xilinx_dma_tx_descriptor, + node); } if (!last) @@ -1081,20 +1116,14 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE, last->hw.stride); vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize); - } - chan->idle = false; - if (!chan->has_sg) { - list_del(&desc->node); - list_add_tail(&desc->node, &chan->active_list); - chan->desc_submitcount++; - chan->desc_pendingcount--; + chan->desc_submitcount += j; + chan->desc_pendingcount -= j; if (chan->desc_submitcount == chan->num_frms) chan->desc_submitcount = 0; - } else { - list_splice_tail_init(&chan->pending_list, &chan->active_list); - chan->desc_pendingcount = 0; } + + chan->idle = false; } /** @@ -1342,6 +1371,7 @@ static int xilinx_dma_reset(struct xilinx_dma_chan *chan) chan->err = false; chan->idle = true; + chan->desc_submitcount = 0; return err; } @@ -2315,6 +2345,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, has_dre = of_property_read_bool(node, "xlnx,include-dre"); chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode"); + chan->has_fstoreconfig = of_property_read_bool(node, + "xlnx,fstore-config"); err = of_property_read_u32(node, "xlnx,datawidth", &value); if (err) { -- 2.1.2 From mboxrd@z Thu Jan 1 00:00:00 1970 From: appana.durga.rao@xilinx.com (Kedareswara rao Appana) Date: Wed, 4 Jan 2017 12:24:06 +0530 Subject: [PATCH v3 2/3] dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in vdma In-Reply-To: <1483512847-25710-1-git-send-email-appanad@xilinx.com> References: <1483512847-25710-1-git-send-email-appanad@xilinx.com> Message-ID: <1483512847-25710-3-git-send-email-appanad@xilinx.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org When VDMA is configured for more than one frame in the h/w for example h/w is configured for n number of frames and user Submits n number of frames and triggered the DMA using issue_pending API. In the current driver flow we are submitting one frame at a time but we should submit all the n number of frames at one time as the h/w Is configured for n number of frames. This patch fixes this issue. Signed-off-by: Kedareswara rao Appana --- Changes for v3: ---> Added Checks for frame store configuration. If frame store Configuration is not present at the h/w level and user Submits less frames added debug prints in the driver as relevant. Changes for v2: ---> Fixed race conditions in the driver as suggested by Jose Abreu ---> Fixed unnecessray if else checks in the vdma_start_transfer as suggested by Laurent Pinchart. .../devicetree/bindings/dma/xilinx/xilinx_dma.txt | 2 + drivers/dma/xilinx/xilinx_dma.c | 78 +++++++++++++++------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt index a2b8bfa..1f65e09 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt @@ -66,6 +66,8 @@ Optional child node properties: Optional child node properties for VDMA: - xlnx,genlock-mode: Tells Genlock synchronization is enabled/disabled in hardware. +- xlnx,fstore-config: Tells Whether Frame Store Configuration is + enabled/disabled in hardware. Optional child node properties for AXI DMA: -dma-channels: Number of dma channels in child node. diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index be7eb41..7cd8e08 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -322,6 +322,7 @@ struct xilinx_dma_tx_descriptor { * @genlock: Support genlock mode * @err: Channel has errors * @idle: Check for channel idle + * @has_fstoreconfig: Check for frame store configuration * @tasklet: Cleanup work after irq * @config: Device configuration info * @flush_on_fsync: Flush on Frame sync @@ -353,6 +354,7 @@ struct xilinx_dma_chan { bool genlock; bool err; bool idle; + bool has_fstoreconfig; struct tasklet_struct tasklet; struct xilinx_vdma_config config; bool flush_on_fsync; @@ -990,6 +992,26 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (list_empty(&chan->pending_list)) return; + /* + * Note: When VDMA is built with default h/w configuration + * On the S2MM(recv) side user should submit frames upto + * H/W configured. If users submits less than h/w configured + * VDMA engine tries to write to a invalid location + * Results undefined behaviour/memory corruption. + * + * If user would like to submit frames less than h/w capable + * On S2MM side please enable debug info 13 at the h/w level + * It will allows the frame buffers numbers to be modified at runtime. + */ + if (!chan->has_fstoreconfig && chan->direction == DMA_DEV_TO_MEM && + chan->desc_pendingcount < chan->num_frms) { + dev_dbg(chan->dev, "Frame Store Configuration is not enabled at the"); + dev_dbg(chan->dev, " H/w level enable Debug info 13 at the h/w level"); + dev_dbg(chan->dev, " OR Submit the frames upto h/w Capable\n\r"); + + return; + } + desc = list_first_entry(&chan->pending_list, struct xilinx_dma_tx_descriptor, node); tail_desc = list_last_entry(&chan->pending_list, @@ -1052,25 +1074,38 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) if (chan->has_sg) { dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC, tail_segment->phys); + list_splice_tail_init(&chan->pending_list, &chan->active_list); + chan->desc_pendingcount = 0; } else { struct xilinx_vdma_tx_segment *segment, *last = NULL; - int i = 0; + int i = 0, j = 0; if (chan->desc_submitcount < chan->num_frms) i = chan->desc_submitcount; - list_for_each_entry(segment, &desc->segments, node) { - if (chan->ext_addr) - vdma_desc_write_64(chan, - XILINX_VDMA_REG_START_ADDRESS_64(i++), - segment->hw.buf_addr, - segment->hw.buf_addr_msb); - else - vdma_desc_write(chan, - XILINX_VDMA_REG_START_ADDRESS(i++), - segment->hw.buf_addr); - - last = segment; + for (j = 0; j < chan->num_frms; ) { + list_for_each_entry(segment, &desc->segments, node) { + if (chan->ext_addr) + vdma_desc_write_64(chan, + XILINX_VDMA_REG_START_ADDRESS_64(i++), + segment->hw.buf_addr, + segment->hw.buf_addr_msb); + else + vdma_desc_write(chan, + XILINX_VDMA_REG_START_ADDRESS(i++), + segment->hw.buf_addr); + + last = segment; + } + list_del(&desc->node); + list_add_tail(&desc->node, &chan->active_list); + j++; + if (list_empty(&chan->pending_list) || + (i == chan->num_frms)) + break; + desc = list_first_entry(&chan->pending_list, + struct xilinx_dma_tx_descriptor, + node); } if (!last) @@ -1081,20 +1116,14 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE, last->hw.stride); vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize); - } - chan->idle = false; - if (!chan->has_sg) { - list_del(&desc->node); - list_add_tail(&desc->node, &chan->active_list); - chan->desc_submitcount++; - chan->desc_pendingcount--; + chan->desc_submitcount += j; + chan->desc_pendingcount -= j; if (chan->desc_submitcount == chan->num_frms) chan->desc_submitcount = 0; - } else { - list_splice_tail_init(&chan->pending_list, &chan->active_list); - chan->desc_pendingcount = 0; } + + chan->idle = false; } /** @@ -1342,6 +1371,7 @@ static int xilinx_dma_reset(struct xilinx_dma_chan *chan) chan->err = false; chan->idle = true; + chan->desc_submitcount = 0; return err; } @@ -2315,6 +2345,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, has_dre = of_property_read_bool(node, "xlnx,include-dre"); chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode"); + chan->has_fstoreconfig = of_property_read_bool(node, + "xlnx,fstore-config"); err = of_property_read_u32(node, "xlnx,datawidth", &value); if (err) { -- 2.1.2