drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c

Source file repositories/reference/linux-study-clean/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
Extension
.c
Size
16991 bytes
Lines
552
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
			netdev_dbg(priv->ndev,
				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n",
				   rx_ring->nr, rx_ring->fifo_nr,
				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
				   priv->rx_obj_num_coalesce_irq, rx_ring->obj_size,
				   priv->rx_obj_num_coalesce_irq * rx_ring->obj_size);

			if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH)
				continue;

			netdev_dbg(priv->ndev,
				   "                         0x%03x: %2u*%u bytes = %4u bytes\n",
				   mcp251xfd_get_rx_obj_addr(rx_ring,
							     priv->rx_obj_num_coalesce_irq),
				   rx_ring->obj_num - priv->rx_obj_num_coalesce_irq,
				   rx_ring->obj_size,
				   (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) *
				   rx_ring->obj_size);
		} else {
			netdev_dbg(priv->ndev,
				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
				   rx_ring->nr, rx_ring->fifo_nr,
				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
				   rx_ring->obj_num, rx_ring->obj_size,
				   rx_ring->obj_num * rx_ring->obj_size);
		}
	}

	netdev_dbg(priv->ndev,
		   "FIFO setup: TX:   FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
		   priv->tx->fifo_nr,
		   mcp251xfd_get_tx_obj_addr(priv->tx, 0),
		   priv->tx->obj_num, priv->tx->obj_size,
		   priv->tx->obj_num * priv->tx->obj_size);

	netdev_dbg(priv->ndev,
		   "FIFO setup: free:                             %4d bytes\n",
		   MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START));

	ram_used = base - MCP251XFD_RAM_START;
	if (ram_used > MCP251XFD_RAM_SIZE) {
		netdev_err(priv->ndev,
			   "Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
			   ram_used, MCP251XFD_RAM_SIZE);
		err = -ENOMEM;
	}

	if (priv->tx_obj_num_coalesce_irq &&
	    priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
		netdev_err(priv->ndev,
			   "Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
			   priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
		err = -EINVAL;
	}

	return err;
}

void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
{
	int i;

	for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) {
		kfree(priv->rx[i]);
		priv->rx[i] = NULL;
	}
}

static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
{
	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
						   rx_irq_timer);
	struct mcp251xfd_rx_ring *ring = priv->rx[0];

	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
		return HRTIMER_NORESTART;

	spi_async(priv->spi, &ring->irq_enable_msg);

	return HRTIMER_NORESTART;
}

static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t)
{
	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
						   tx_irq_timer);
	struct mcp251xfd_tef_ring *ring = priv->tef;

	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))

Annotation

Implementation Notes