drivers/net/ethernet/marvell/prestera/prestera_flow.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/prestera/prestera_flow.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/prestera/prestera_flow.c
Extension
.c
Size
7271 bytes
Lines
316
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 (IS_ERR(block_cb)) {
			prestera_flow_block_destroy(block);
			return ERR_CAST(block_cb);
		}

		block->block_cb = block_cb;
		*register_block = true;
	} else {
		block = flow_block_cb_priv(block_cb);
		*register_block = false;
	}

	flow_block_cb_incref(block_cb);

	return block;
}

static void prestera_flow_block_put(struct prestera_flow_block *block)
{
	struct flow_block_cb *block_cb = block->block_cb;

	if (flow_block_cb_decref(block_cb))
		return;

	flow_block_cb_free(block_cb);
	prestera_flow_block_destroy(block);
}

static int prestera_setup_flow_block_bind(struct prestera_port *port,
					  struct flow_block_offload *f, bool ingress)
{
	struct prestera_switch *sw = port->sw;
	struct prestera_flow_block *block;
	struct flow_block_cb *block_cb;
	bool register_block;
	int err;

	block = prestera_flow_block_get(sw, f, &register_block, ingress);
	if (IS_ERR(block))
		return PTR_ERR(block);

	block_cb = block->block_cb;

	err = prestera_flow_block_bind(block, port);
	if (err)
		goto err_block_bind;

	if (register_block) {
		flow_block_cb_add(block_cb, f);
		list_add_tail(&block_cb->driver_list, &prestera_block_cb_list);
	}

	if (ingress)
		port->ingress_flow_block = block;
	else
		port->egress_flow_block = block;

	return 0;

err_block_bind:
	prestera_flow_block_put(block);

	return err;
}

static void prestera_setup_flow_block_unbind(struct prestera_port *port,
					     struct flow_block_offload *f, bool ingress)
{
	struct prestera_switch *sw = port->sw;
	struct prestera_flow_block *block;
	struct flow_block_cb *block_cb;
	int err;

	block_cb = flow_block_cb_lookup(f->block, prestera_flow_block_cb, sw);
	if (!block_cb)
		return;

	block = flow_block_cb_priv(block_cb);

	prestera_mall_destroy(block);

	err = prestera_flow_block_unbind(block, port);
	if (err)
		goto error;

	if (!flow_block_cb_decref(block_cb)) {
		flow_block_cb_remove(block_cb, f);
		list_del(&block_cb->driver_list);
	}
error:

Annotation

Implementation Notes