.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2006 ARM Ltd. |
---|
3 | 4 | * Copyright (c) 2010 ST-Ericsson SA |
---|
.. | .. |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Peter Pearse <peter.pearse@arm.com> |
---|
7 | 8 | * Author: Linus Walleij <linus.walleij@linaro.org> |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify it |
---|
10 | | - * under the terms of the GNU General Public License as published by the Free |
---|
11 | | - * Software Foundation; either version 2 of the License, or (at your option) |
---|
12 | | - * any later version. |
---|
13 | | - * |
---|
14 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
15 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
16 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
17 | | - * more details. |
---|
18 | | - * |
---|
19 | | - * The full GNU General Public License is in this distribution in the file |
---|
20 | | - * called COPYING. |
---|
21 | 9 | * |
---|
22 | 10 | * Documentation: ARM DDI 0196G == PL080 |
---|
23 | 11 | * Documentation: ARM DDI 0218E == PL081 |
---|
.. | .. |
---|
254 | 242 | * @slave: whether this channel is a device (slave) or for memcpy |
---|
255 | 243 | * @signal: the physical DMA request signal which this channel is using |
---|
256 | 244 | * @mux_use: count of descriptors using this DMA request signal setting |
---|
| 245 | + * @waiting_at: time in jiffies when this channel moved to waiting state |
---|
257 | 246 | */ |
---|
258 | 247 | struct pl08x_dma_chan { |
---|
259 | 248 | struct virt_dma_chan vc; |
---|
.. | .. |
---|
267 | 256 | bool slave; |
---|
268 | 257 | int signal; |
---|
269 | 258 | unsigned mux_use; |
---|
| 259 | + unsigned long waiting_at; |
---|
270 | 260 | }; |
---|
271 | 261 | |
---|
272 | 262 | /** |
---|
.. | .. |
---|
875 | 865 | if (!ch) { |
---|
876 | 866 | dev_dbg(&pl08x->adev->dev, "no physical channel available for xfer on %s\n", plchan->name); |
---|
877 | 867 | plchan->state = PL08X_CHAN_WAITING; |
---|
| 868 | + plchan->waiting_at = jiffies; |
---|
878 | 869 | return; |
---|
879 | 870 | } |
---|
880 | 871 | |
---|
.. | .. |
---|
913 | 904 | { |
---|
914 | 905 | struct pl08x_driver_data *pl08x = plchan->host; |
---|
915 | 906 | struct pl08x_dma_chan *p, *next; |
---|
916 | | - |
---|
| 907 | + unsigned long waiting_at; |
---|
917 | 908 | retry: |
---|
918 | 909 | next = NULL; |
---|
| 910 | + waiting_at = jiffies; |
---|
919 | 911 | |
---|
920 | | - /* Find a waiting virtual channel for the next transfer. */ |
---|
| 912 | + /* |
---|
| 913 | + * Find a waiting virtual channel for the next transfer. |
---|
| 914 | + * To be fair, time when each channel reached waiting state is compared |
---|
| 915 | + * to select channel that is waiting for the longest time. |
---|
| 916 | + */ |
---|
921 | 917 | list_for_each_entry(p, &pl08x->memcpy.channels, vc.chan.device_node) |
---|
922 | | - if (p->state == PL08X_CHAN_WAITING) { |
---|
| 918 | + if (p->state == PL08X_CHAN_WAITING && |
---|
| 919 | + p->waiting_at <= waiting_at) { |
---|
923 | 920 | next = p; |
---|
924 | | - break; |
---|
| 921 | + waiting_at = p->waiting_at; |
---|
925 | 922 | } |
---|
926 | 923 | |
---|
927 | 924 | if (!next && pl08x->has_slave) { |
---|
928 | 925 | list_for_each_entry(p, &pl08x->slave.channels, vc.chan.device_node) |
---|
929 | | - if (p->state == PL08X_CHAN_WAITING) { |
---|
| 926 | + if (p->state == PL08X_CHAN_WAITING && |
---|
| 927 | + p->waiting_at <= waiting_at) { |
---|
930 | 928 | next = p; |
---|
931 | | - break; |
---|
| 929 | + waiting_at = p->waiting_at; |
---|
932 | 930 | } |
---|
933 | 931 | } |
---|
934 | 932 | |
---|
.. | .. |
---|
1769 | 1767 | default: |
---|
1770 | 1768 | dev_err(&pl08x->adev->dev, |
---|
1771 | 1769 | "illegal burst size for memcpy, set to 1\n"); |
---|
1772 | | - /* Fall through */ |
---|
| 1770 | + fallthrough; |
---|
1773 | 1771 | case PL08X_BURST_SZ_1: |
---|
1774 | 1772 | cctl |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT | |
---|
1775 | 1773 | PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT; |
---|
.. | .. |
---|
1808 | 1806 | default: |
---|
1809 | 1807 | dev_err(&pl08x->adev->dev, |
---|
1810 | 1808 | "illegal bus width for memcpy, set to 8 bits\n"); |
---|
1811 | | - /* Fall through */ |
---|
| 1809 | + fallthrough; |
---|
1812 | 1810 | case PL08X_BUS_WIDTH_8_BITS: |
---|
1813 | 1811 | cctl |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT | |
---|
1814 | 1812 | PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT; |
---|
.. | .. |
---|
1852 | 1850 | default: |
---|
1853 | 1851 | dev_err(&pl08x->adev->dev, |
---|
1854 | 1852 | "illegal bus width for memcpy, set to 8 bits\n"); |
---|
1855 | | - /* Fall through */ |
---|
| 1853 | + fallthrough; |
---|
1856 | 1854 | case PL08X_BUS_WIDTH_8_BITS: |
---|
1857 | 1855 | cctl |= PL080_WIDTH_8BIT << FTDMAC020_LLI_SRC_WIDTH_SHIFT | |
---|
1858 | 1856 | PL080_WIDTH_8BIT << FTDMAC020_LLI_DST_WIDTH_SHIFT; |
---|
.. | .. |
---|
2505 | 2503 | return 0; |
---|
2506 | 2504 | } |
---|
2507 | 2505 | |
---|
2508 | | -static int pl08x_debugfs_open(struct inode *inode, struct file *file) |
---|
2509 | | -{ |
---|
2510 | | - return single_open(file, pl08x_debugfs_show, inode->i_private); |
---|
2511 | | -} |
---|
2512 | | - |
---|
2513 | | -static const struct file_operations pl08x_debugfs_operations = { |
---|
2514 | | - .open = pl08x_debugfs_open, |
---|
2515 | | - .read = seq_read, |
---|
2516 | | - .llseek = seq_lseek, |
---|
2517 | | - .release = single_release, |
---|
2518 | | -}; |
---|
| 2506 | +DEFINE_SHOW_ATTRIBUTE(pl08x_debugfs); |
---|
2519 | 2507 | |
---|
2520 | 2508 | static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) |
---|
2521 | 2509 | { |
---|
2522 | 2510 | /* Expose a simple debugfs interface to view all clocks */ |
---|
2523 | | - (void) debugfs_create_file(dev_name(&pl08x->adev->dev), |
---|
2524 | | - S_IFREG | S_IRUGO, NULL, pl08x, |
---|
2525 | | - &pl08x_debugfs_operations); |
---|
| 2511 | + debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO, |
---|
| 2512 | + NULL, pl08x, &pl08x_debugfs_fops); |
---|
2526 | 2513 | } |
---|
2527 | 2514 | |
---|
2528 | 2515 | #else |
---|
.. | .. |
---|
2625 | 2612 | switch (val) { |
---|
2626 | 2613 | default: |
---|
2627 | 2614 | dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n"); |
---|
2628 | | - /* Fall through */ |
---|
| 2615 | + fallthrough; |
---|
2629 | 2616 | case 1: |
---|
2630 | 2617 | pd->memcpy_burst_size = PL08X_BURST_SZ_1; |
---|
2631 | 2618 | break; |
---|
.. | .. |
---|
2660 | 2647 | switch (val) { |
---|
2661 | 2648 | default: |
---|
2662 | 2649 | dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); |
---|
2663 | | - /* Fall through */ |
---|
| 2650 | + fallthrough; |
---|
2664 | 2651 | case 8: |
---|
2665 | 2652 | pd->memcpy_bus_width = PL08X_BUS_WIDTH_8_BITS; |
---|
2666 | 2653 | break; |
---|