cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mcp251xfd-ram.c (4223B)


      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 <kernel@pengutronix.de>
      7//
      8
      9#include "mcp251xfd-ram.h"
     10
     11static 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
     21static u8
     22can_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
     60void 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}