| .. | .. |
|---|
| 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; |
|---|