0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "mcp251xfd-ram.h"
0010
0011 static inline u8 can_ram_clamp(const struct can_ram_config *config,
0012 const struct can_ram_obj_config *obj,
0013 u8 val)
0014 {
0015 u8 max;
0016
0017 max = min_t(u8, obj->max, obj->fifo_num * config->fifo_depth);
0018 return clamp(val, obj->min, max);
0019 }
0020
0021 static u8
0022 can_ram_rounddown_pow_of_two(const struct can_ram_config *config,
0023 const struct can_ram_obj_config *obj,
0024 const u8 coalesce, u8 val)
0025 {
0026 u8 fifo_num = obj->fifo_num;
0027 u8 ret = 0, i;
0028
0029 val = can_ram_clamp(config, obj, val);
0030
0031 if (coalesce) {
0032
0033
0034
0035
0036
0037
0038 ret = min_t(u8, coalesce * 2, config->fifo_depth);
0039 val -= ret;
0040 fifo_num--;
0041 }
0042
0043 for (i = 0; i < fifo_num && val; i++) {
0044 u8 n;
0045
0046 n = min_t(u8, rounddown_pow_of_two(val),
0047 config->fifo_depth);
0048
0049
0050 if (n < obj->fifo_depth_min)
0051 return ret;
0052
0053 ret += n;
0054 val -= n;
0055 }
0056
0057 return ret;
0058 }
0059
0060 void can_ram_get_layout(struct can_ram_layout *layout,
0061 const struct can_ram_config *config,
0062 const struct ethtool_ringparam *ring,
0063 const struct ethtool_coalesce *ec,
0064 const bool fd_mode)
0065 {
0066 u8 num_rx, num_tx;
0067 u16 ram_free;
0068
0069
0070
0071 num_tx = config->tx.def[fd_mode];
0072 num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
0073
0074 ram_free = config->size;
0075 ram_free -= config->tx.size[fd_mode] * num_tx;
0076
0077 num_rx = ram_free / config->rx.size[fd_mode];
0078
0079 layout->default_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
0080 layout->default_tx = num_tx;
0081
0082
0083
0084 ram_free = config->size;
0085 ram_free -= config->tx.size[fd_mode] * config->tx.min;
0086 num_rx = ram_free / config->rx.size[fd_mode];
0087
0088 ram_free = config->size;
0089 ram_free -= config->rx.size[fd_mode] * config->rx.min;
0090 num_tx = ram_free / config->tx.size[fd_mode];
0091
0092 layout->max_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
0093 layout->max_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
0094
0095
0096
0097 if (ring) {
0098 u8 num_rx_coalesce = 0, num_tx_coalesce = 0;
0099
0100 num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, ring->rx_pending);
0101
0102
0103
0104
0105 if (ec && !(ec->rx_coalesce_usecs_irq == 0 &&
0106 ec->rx_max_coalesced_frames_irq == 1)) {
0107 u8 max;
0108
0109
0110 max = min_t(u8, num_rx / 2, config->fifo_depth);
0111 num_rx_coalesce = clamp(ec->rx_max_coalesced_frames_irq,
0112 (u32)config->rx.fifo_depth_coalesce_min,
0113 (u32)max);
0114 num_rx_coalesce = rounddown_pow_of_two(num_rx_coalesce);
0115
0116 num_rx = can_ram_rounddown_pow_of_two(config, &config->rx,
0117 num_rx_coalesce, num_rx);
0118 }
0119
0120 ram_free = config->size - config->rx.size[fd_mode] * num_rx;
0121 num_tx = ram_free / config->tx.size[fd_mode];
0122 num_tx = min_t(u8, ring->tx_pending, num_tx);
0123 num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
0124
0125
0126
0127
0128 if (ec && !(ec->tx_coalesce_usecs_irq == 0 &&
0129 ec->tx_max_coalesced_frames_irq == 1)) {
0130 u8 max;
0131
0132
0133 max = min_t(u8, num_tx / 2, config->fifo_depth);
0134 num_tx_coalesce = clamp(ec->tx_max_coalesced_frames_irq,
0135 (u32)config->tx.fifo_depth_coalesce_min,
0136 (u32)max);
0137 num_tx_coalesce = rounddown_pow_of_two(num_tx_coalesce);
0138
0139 num_tx = can_ram_rounddown_pow_of_two(config, &config->tx,
0140 num_tx_coalesce, num_tx);
0141 }
0142
0143 layout->cur_rx = num_rx;
0144 layout->cur_tx = num_tx;
0145 layout->rx_coalesce = num_rx_coalesce;
0146 layout->tx_coalesce = num_tx_coalesce;
0147 } else {
0148 layout->cur_rx = layout->default_rx;
0149 layout->cur_tx = layout->default_tx;
0150 layout->rx_coalesce = 0;
0151 layout->tx_coalesce = 0;
0152 }
0153 }