brintos

brintos / linux-shallow public Read only

0
0
Text · 4.4 KiB · 61b0d6f Raw
163 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// mcp251xfd - Microchip MCP251xFD Family CAN controller driver4//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 u822can_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) for35		 * coalescing or only half of FIFO (FIFO Half Full36		 * 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		/* If the ring parameters have been configured in101		 * CAN-CC mode, but and we are in CAN-FD mode now,102		 * they might be to big. Use the default CAN-FD values103		 * in this case.104		 */105		num_rx = ring->rx_pending;106		if (num_rx > layout->max_rx)107			num_rx = layout->default_rx;108 109		num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);110 111		/* The ethtool doc says:112		 * To disable coalescing, set usecs = 0 and max_frames = 1.113		 */114		if (ec && !(ec->rx_coalesce_usecs_irq == 0 &&115			    ec->rx_max_coalesced_frames_irq == 1)) {116			u8 max;117 118			/* use only max half of available objects for coalescing */119			max = min_t(u8, num_rx / 2, config->fifo_depth);120			num_rx_coalesce = clamp(ec->rx_max_coalesced_frames_irq,121						(u32)config->rx.fifo_depth_coalesce_min,122						(u32)max);123			num_rx_coalesce = rounddown_pow_of_two(num_rx_coalesce);124 125			num_rx = can_ram_rounddown_pow_of_two(config, &config->rx,126							      num_rx_coalesce, num_rx);127		}128 129		ram_free = config->size - config->rx.size[fd_mode] * num_rx;130		num_tx = ram_free / config->tx.size[fd_mode];131		num_tx = min_t(u8, ring->tx_pending, num_tx);132		num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);133 134		/* The ethtool doc says:135		 * To disable coalescing, set usecs = 0 and max_frames = 1.136		 */137		if (ec && !(ec->tx_coalesce_usecs_irq == 0 &&138			    ec->tx_max_coalesced_frames_irq == 1)) {139			u8 max;140 141			/* use only max half of available objects for coalescing */142			max = min_t(u8, num_tx / 2, config->fifo_depth);143			num_tx_coalesce = clamp(ec->tx_max_coalesced_frames_irq,144						(u32)config->tx.fifo_depth_coalesce_min,145						(u32)max);146			num_tx_coalesce = rounddown_pow_of_two(num_tx_coalesce);147 148			num_tx = can_ram_rounddown_pow_of_two(config, &config->tx,149							      num_tx_coalesce, num_tx);150		}151 152		layout->cur_rx = num_rx;153		layout->cur_tx = num_tx;154		layout->rx_coalesce = num_rx_coalesce;155		layout->tx_coalesce = num_tx_coalesce;156	} else {157		layout->cur_rx = layout->default_rx;158		layout->cur_tx = layout->default_tx;159		layout->rx_coalesce = 0;160		layout->tx_coalesce = 0;161	}162}163