|  | // SPDX-License-Identifier: GPL-2.0+ | 
|  |  | 
|  | #include "lan966x_main.h" | 
|  |  | 
|  | int lan966x_cbs_add(struct lan966x_port *port, | 
|  | struct tc_cbs_qopt_offload *qopt) | 
|  | { | 
|  | struct lan966x *lan966x = port->lan966x; | 
|  | u32 cir, cbs; | 
|  | u8 se_idx; | 
|  |  | 
|  | /* Check for invalid values */ | 
|  | if (qopt->idleslope <= 0 || | 
|  | qopt->sendslope >= 0 || | 
|  | qopt->locredit >= qopt->hicredit) | 
|  | return -EINVAL; | 
|  |  | 
|  | se_idx = SE_IDX_QUEUE + port->chip_port * NUM_PRIO_QUEUES + qopt->queue; | 
|  | cir = qopt->idleslope; | 
|  | cbs = (qopt->idleslope - qopt->sendslope) * | 
|  | (qopt->hicredit - qopt->locredit) / | 
|  | -qopt->sendslope; | 
|  |  | 
|  | /* Rate unit is 100 kbps */ | 
|  | cir = DIV_ROUND_UP(cir, 100); | 
|  | /* Avoid using zero rate */ | 
|  | cir = cir ?: 1; | 
|  | /* Burst unit is 4kB */ | 
|  | cbs = DIV_ROUND_UP(cbs, 4096); | 
|  | /* Avoid using zero burst */ | 
|  | cbs = cbs ?: 1; | 
|  |  | 
|  | /* Check that actually the result can be written */ | 
|  | if (cir > GENMASK(15, 0) || | 
|  | cbs > GENMASK(6, 0)) | 
|  | return -EINVAL; | 
|  |  | 
|  | lan_rmw(QSYS_SE_CFG_SE_AVB_ENA_SET(1) | | 
|  | QSYS_SE_CFG_SE_FRM_MODE_SET(1), | 
|  | QSYS_SE_CFG_SE_AVB_ENA | | 
|  | QSYS_SE_CFG_SE_FRM_MODE, | 
|  | lan966x, QSYS_SE_CFG(se_idx)); | 
|  |  | 
|  | lan_wr(QSYS_CIR_CFG_CIR_RATE_SET(cir) | | 
|  | QSYS_CIR_CFG_CIR_BURST_SET(cbs), | 
|  | lan966x, QSYS_CIR_CFG(se_idx)); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int lan966x_cbs_del(struct lan966x_port *port, | 
|  | struct tc_cbs_qopt_offload *qopt) | 
|  | { | 
|  | struct lan966x *lan966x = port->lan966x; | 
|  | u8 se_idx; | 
|  |  | 
|  | se_idx = SE_IDX_QUEUE + port->chip_port * NUM_PRIO_QUEUES + qopt->queue; | 
|  |  | 
|  | lan_rmw(QSYS_SE_CFG_SE_AVB_ENA_SET(1) | | 
|  | QSYS_SE_CFG_SE_FRM_MODE_SET(0), | 
|  | QSYS_SE_CFG_SE_AVB_ENA | | 
|  | QSYS_SE_CFG_SE_FRM_MODE, | 
|  | lan966x, QSYS_SE_CFG(se_idx)); | 
|  |  | 
|  | lan_wr(QSYS_CIR_CFG_CIR_RATE_SET(0) | | 
|  | QSYS_CIR_CFG_CIR_BURST_SET(0), | 
|  | lan966x, QSYS_CIR_CFG(se_idx)); | 
|  |  | 
|  | return 0; | 
|  | } |