drivers/net/ethernet/microchip/lan966x/lan966x_police.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/lan966x/lan966x_police.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/lan966x/lan966x_police.c
Extension
.c
Size
6056 bytes
Lines
227
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

struct lan966x_tc_policer {
	/* kilobit per second */
	u32 rate;
	/* bytes */
	u32 burst;
};

static int lan966x_police_add(struct lan966x_port *port,
			      struct lan966x_tc_policer *pol,
			      u16 pol_idx)
{
	struct lan966x *lan966x = port->lan966x;

	/* Rate unit is 33 1/3 kpps */
	pol->rate = DIV_ROUND_UP(pol->rate * 3, 100);
	/* Avoid zero burst size */
	pol->burst = pol->burst ?: 1;
	/* Unit is 4kB */
	pol->burst = DIV_ROUND_UP(pol->burst, 4096);

	if (pol->rate > GENMASK(15, 0) ||
	    pol->burst > GENMASK(6, 0))
		return -EINVAL;

	lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
	       ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
	       ANA_POL_MODE_IPG_SIZE_SET(20) |
	       ANA_POL_MODE_FRM_MODE_SET(1) |
	       ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
	       lan966x, ANA_POL_MODE(pol_idx));

	lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
	       lan966x, ANA_POL_PIR_STATE(pol_idx));

	lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(pol->rate) |
	       ANA_POL_PIR_CFG_PIR_BURST_SET(pol->burst),
	       lan966x, ANA_POL_PIR_CFG(pol_idx));

	return 0;
}

static void lan966x_police_del(struct lan966x_port *port, u16 pol_idx)
{
	struct lan966x *lan966x = port->lan966x;

	lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
	       ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
	       ANA_POL_MODE_IPG_SIZE_SET(20) |
	       ANA_POL_MODE_FRM_MODE_SET(2) |
	       ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
	       lan966x, ANA_POL_MODE(pol_idx));

	lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
	       lan966x, ANA_POL_PIR_STATE(pol_idx));

	lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |
	       ANA_POL_PIR_CFG_PIR_BURST_SET(0),
	       lan966x, ANA_POL_PIR_CFG(pol_idx));
}

static int lan966x_police_validate(struct lan966x_port *port,
				   const struct flow_action *action,
				   const struct flow_action_entry *act,
				   unsigned long police_id,
				   bool ingress,
				   struct netlink_ext_ack *extack)
{
	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Offload not supported when exceed action is not drop");
		return -EOPNOTSUPP;
	}

	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Offload not supported when conform action is not pipe or ok");
		return -EOPNOTSUPP;
	}

	if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
	    !flow_action_is_last_entry(action, act)) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Offload not supported when conform action is ok, but action is not last");
		return -EOPNOTSUPP;
	}

	if (act->police.peakrate_bytes_ps ||
	    act->police.avrate || act->police.overhead) {
		NL_SET_ERR_MSG_MOD(extack,

Annotation

Implementation Notes