drivers/net/ethernet/broadcom/bcmsysport.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bcmsysport.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bcmsysport.c
Extension
.c
Size
77235 bytes
Lines
2896
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops bcm_sysport_netdev_ops = {
	.ndo_start_xmit		= bcm_sysport_xmit,
	.ndo_tx_timeout		= bcm_sysport_tx_timeout,
	.ndo_open		= bcm_sysport_open,
	.ndo_stop		= bcm_sysport_stop,
	.ndo_set_features	= bcm_sysport_set_features,
	.ndo_set_rx_mode	= bcm_sysport_set_rx_mode,
	.ndo_set_mac_address	= bcm_sysport_change_mac,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= bcm_sysport_poll_controller,
#endif
	.ndo_get_stats64	= bcm_sysport_get_stats64,
	.ndo_select_queue	= bcm_sysport_select_queue,
};

static int bcm_sysport_map_queues(struct net_device *dev,
				  struct net_device *slave_dev)
{
	struct dsa_port *dp = dsa_port_from_netdev(slave_dev);
	struct bcm_sysport_priv *priv = netdev_priv(dev);
	struct bcm_sysport_tx_ring *ring;
	unsigned int num_tx_queues;
	unsigned int q, qp, port;

	/* We can't be setting up queue inspection for non directly attached
	 * switches
	 */
	if (dp->ds->index)
		return 0;

	port = dp->index;

	/* On SYSTEMPORT Lite we have twice as less queues, so we cannot do a
	 * 1:1 mapping, we can only do a 2:1 mapping. By reducing the number of
	 * per-port (slave_dev) network devices queue, we achieve just that.
	 * This need to happen now before any slave network device is used such
	 * it accurately reflects the number of real TX queues.
	 */
	if (priv->is_lite)
		netif_set_real_num_tx_queues(slave_dev,
					     slave_dev->num_tx_queues / 2);

	num_tx_queues = slave_dev->real_num_tx_queues;

	if (priv->per_port_num_tx_queues &&
	    priv->per_port_num_tx_queues != num_tx_queues)
		netdev_warn(slave_dev, "asymmetric number of per-port queues\n");

	priv->per_port_num_tx_queues = num_tx_queues;

	for (q = 0, qp = 0; q < dev->num_tx_queues && qp < num_tx_queues;
	     q++) {
		ring = &priv->tx_rings[q];

		if (ring->inspect)
			continue;

		/* Just remember the mapping actual programming done
		 * during bcm_sysport_init_tx_ring
		 */
		ring->switch_queue = qp;
		ring->switch_port = port;
		ring->inspect = true;
		priv->ring_map[qp + port * num_tx_queues] = ring;
		qp++;
	}

	return 0;
}

static int bcm_sysport_unmap_queues(struct net_device *dev,
				    struct net_device *slave_dev)
{
	struct dsa_port *dp = dsa_port_from_netdev(slave_dev);
	struct bcm_sysport_priv *priv = netdev_priv(dev);
	struct bcm_sysport_tx_ring *ring;
	unsigned int num_tx_queues;
	unsigned int q, qp, port;

	port = dp->index;

	num_tx_queues = slave_dev->real_num_tx_queues;

	for (q = 0; q < dev->num_tx_queues; q++) {
		ring = &priv->tx_rings[q];

		if (ring->switch_port != port)
			continue;

		if (!ring->inspect)

Annotation

Implementation Notes