]> Git Repo - linux.git/blob - drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
net: bgmac: Fix return value check for fixed_phy_register()
[linux.git] / drivers / net / can / spi / mcp251xfd / mcp251xfd-ram.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
4 //
5 // Copyright (c) 2021, 2022 Pengutronix,
6 //               Marc Kleine-Budde <[email protected]>
7 //
8
9 #include "mcp251xfd-ram.h"
10
11 static inline u8 can_ram_clamp(const struct can_ram_config *config,
12                                const struct can_ram_obj_config *obj,
13                                u8 val)
14 {
15         u8 max;
16
17         max = min_t(u8, obj->max, obj->fifo_num * config->fifo_depth);
18         return clamp(val, obj->min, max);
19 }
20
21 static u8
22 can_ram_rounddown_pow_of_two(const struct can_ram_config *config,
23                              const struct can_ram_obj_config *obj,
24                              const u8 coalesce, u8 val)
25 {
26         u8 fifo_num = obj->fifo_num;
27         u8 ret = 0, i;
28
29         val = can_ram_clamp(config, obj, val);
30
31         if (coalesce) {
32                 /* Use 1st FIFO for coalescing, if requested.
33                  *
34                  * Either use complete FIFO (and FIFO Full IRQ) for
35                  * coalescing or only half of FIFO (FIFO Half Full
36                  * IRQ) and use remaining half for normal objects.
37                  */
38                 ret = min_t(u8, coalesce * 2, config->fifo_depth);
39                 val -= ret;
40                 fifo_num--;
41         }
42
43         for (i = 0; i < fifo_num && val; i++) {
44                 u8 n;
45
46                 n = min_t(u8, rounddown_pow_of_two(val),
47                           config->fifo_depth);
48
49                 /* skip small FIFOs */
50                 if (n < obj->fifo_depth_min)
51                         return ret;
52
53                 ret += n;
54                 val -= n;
55         }
56
57         return ret;
58 }
59
60 void can_ram_get_layout(struct can_ram_layout *layout,
61                         const struct can_ram_config *config,
62                         const struct ethtool_ringparam *ring,
63                         const struct ethtool_coalesce *ec,
64                         const bool fd_mode)
65 {
66         u8 num_rx, num_tx;
67         u16 ram_free;
68
69         /* default CAN */
70
71         num_tx = config->tx.def[fd_mode];
72         num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
73
74         ram_free = config->size;
75         ram_free -= config->tx.size[fd_mode] * num_tx;
76
77         num_rx = ram_free / config->rx.size[fd_mode];
78
79         layout->default_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
80         layout->default_tx = num_tx;
81
82         /* MAX CAN */
83
84         ram_free = config->size;
85         ram_free -= config->tx.size[fd_mode] * config->tx.min;
86         num_rx = ram_free / config->rx.size[fd_mode];
87
88         ram_free = config->size;
89         ram_free -= config->rx.size[fd_mode] * config->rx.min;
90         num_tx = ram_free / config->tx.size[fd_mode];
91
92         layout->max_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
93         layout->max_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
94
95         /* cur CAN */
96
97         if (ring) {
98                 u8 num_rx_coalesce = 0, num_tx_coalesce = 0;
99
100                 num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, ring->rx_pending);
101
102                 /* The ethtool doc says:
103                  * To disable coalescing, set usecs = 0 and max_frames = 1.
104                  */
105                 if (ec && !(ec->rx_coalesce_usecs_irq == 0 &&
106                             ec->rx_max_coalesced_frames_irq == 1)) {
107                         u8 max;
108
109                         /* use only max half of available objects for coalescing */
110                         max = min_t(u8, num_rx / 2, config->fifo_depth);
111                         num_rx_coalesce = clamp(ec->rx_max_coalesced_frames_irq,
112                                                 (u32)config->rx.fifo_depth_coalesce_min,
113                                                 (u32)max);
114                         num_rx_coalesce = rounddown_pow_of_two(num_rx_coalesce);
115
116                         num_rx = can_ram_rounddown_pow_of_two(config, &config->rx,
117                                                               num_rx_coalesce, num_rx);
118                 }
119
120                 ram_free = config->size - config->rx.size[fd_mode] * num_rx;
121                 num_tx = ram_free / config->tx.size[fd_mode];
122                 num_tx = min_t(u8, ring->tx_pending, num_tx);
123                 num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
124
125                 /* The ethtool doc says:
126                  * To disable coalescing, set usecs = 0 and max_frames = 1.
127                  */
128                 if (ec && !(ec->tx_coalesce_usecs_irq == 0 &&
129                             ec->tx_max_coalesced_frames_irq == 1)) {
130                         u8 max;
131
132                         /* use only max half of available objects for coalescing */
133                         max = min_t(u8, num_tx / 2, config->fifo_depth);
134                         num_tx_coalesce = clamp(ec->tx_max_coalesced_frames_irq,
135                                                 (u32)config->tx.fifo_depth_coalesce_min,
136                                                 (u32)max);
137                         num_tx_coalesce = rounddown_pow_of_two(num_tx_coalesce);
138
139                         num_tx = can_ram_rounddown_pow_of_two(config, &config->tx,
140                                                               num_tx_coalesce, num_tx);
141                 }
142
143                 layout->cur_rx = num_rx;
144                 layout->cur_tx = num_tx;
145                 layout->rx_coalesce = num_rx_coalesce;
146                 layout->tx_coalesce = num_tx_coalesce;
147         } else {
148                 layout->cur_rx = layout->default_rx;
149                 layout->cur_tx = layout->default_tx;
150                 layout->rx_coalesce = 0;
151                 layout->tx_coalesce = 0;
152         }
153 }
This page took 0.042814 seconds and 4 git commands to generate.