soc: fsl: dpio: add support for irq coalescing per software portal
In DPAA2 based SoCs, the IRQ coalesing support per software portal has 2 configurable parameters: - the IRQ timeout period (QBMAN_CINH_SWP_ITPR): how many 256 QBMAN cycles need to pass until a dequeue interrupt is asserted. - the IRQ threshold (QBMAN_CINH_SWP_DQRR_ITR): how many dequeue responses in the DQRR ring would generate an IRQ. Add support for setting up and querying these IRQ coalescing related parameters. Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2cf0b6fe9b
commit
ed1d2143fe
@ -114,6 +114,7 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
|
||||
struct device *dev)
|
||||
{
|
||||
struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
|
||||
u32 qman_256_cycles_per_ns;
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
@ -129,6 +130,13 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
|
||||
obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
|
||||
obj->swp_desc.qman_clk = obj->dpio_desc.qman_clk;
|
||||
obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
|
||||
|
||||
/* Compute how many 256 QBMAN cycles fit into one ns. This is because
|
||||
* the interrupt timeout period register needs to be specified in QBMAN
|
||||
* clock cycles in increments of 256.
|
||||
*/
|
||||
qman_256_cycles_per_ns = 256000 / (obj->swp_desc.qman_clk / 1000000);
|
||||
obj->swp_desc.qman_256_cycles_per_ns = qman_256_cycles_per_ns;
|
||||
obj->swp = qbman_swp_init(&obj->swp_desc);
|
||||
|
||||
if (!obj->swp) {
|
||||
@ -780,3 +788,32 @@ int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, u32 *num)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count);
|
||||
|
||||
/**
|
||||
* dpaa2_io_set_irq_coalescing() - Set new IRQ coalescing values
|
||||
* @d: the given DPIO object
|
||||
* @irq_holdoff: interrupt holdoff (timeout) period in us
|
||||
*
|
||||
* Return 0 for success, or negative error code on error.
|
||||
*/
|
||||
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff)
|
||||
{
|
||||
struct qbman_swp *swp = d->swp;
|
||||
|
||||
return qbman_swp_set_irq_coalescing(swp, swp->dqrr.dqrr_size - 1,
|
||||
irq_holdoff);
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_set_irq_coalescing);
|
||||
|
||||
/**
|
||||
* dpaa2_io_get_irq_coalescing() - Get the current IRQ coalescing parameters
|
||||
* @d: the given DPIO object
|
||||
* @irq_holdoff: interrupt holdoff (timeout) period in us
|
||||
*/
|
||||
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff)
|
||||
{
|
||||
struct qbman_swp *swp = d->swp;
|
||||
|
||||
qbman_swp_get_irq_coalescing(swp, NULL, irq_holdoff);
|
||||
}
|
||||
EXPORT_SYMBOL(dpaa2_io_get_irq_coalescing);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define QBMAN_CINH_SWP_EQCR_AM_RT 0x980
|
||||
#define QBMAN_CINH_SWP_RCR_AM_RT 0x9c0
|
||||
#define QBMAN_CINH_SWP_DQPI 0xa00
|
||||
#define QBMAN_CINH_SWP_DQRR_ITR 0xa80
|
||||
#define QBMAN_CINH_SWP_DCAP 0xac0
|
||||
#define QBMAN_CINH_SWP_SDQCR 0xb00
|
||||
#define QBMAN_CINH_SWP_EQCR_AM_RT2 0xb40
|
||||
@ -38,6 +39,7 @@
|
||||
#define QBMAN_CINH_SWP_IER 0xe40
|
||||
#define QBMAN_CINH_SWP_ISDR 0xe80
|
||||
#define QBMAN_CINH_SWP_IIR 0xec0
|
||||
#define QBMAN_CINH_SWP_ITPR 0xf40
|
||||
|
||||
/* CENA register offsets */
|
||||
#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6))
|
||||
@ -355,6 +357,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
|
||||
& p->eqcr.pi_ci_mask;
|
||||
p->eqcr.available = p->eqcr.pi_ring_size;
|
||||
|
||||
/* Initialize the software portal with a irq timeout period of 0us */
|
||||
qbman_swp_set_irq_coalescing(p, p->dqrr.dqrr_size - 1, 0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -1796,3 +1801,57 @@ u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
|
||||
{
|
||||
return le32_to_cpu(a->fill);
|
||||
}
|
||||
|
||||
/**
|
||||
* qbman_swp_set_irq_coalescing() - Set new IRQ coalescing values
|
||||
* @p: the software portal object
|
||||
* @irq_threshold: interrupt threshold
|
||||
* @irq_holdoff: interrupt holdoff (timeout) period in us
|
||||
*
|
||||
* Return 0 for success, or negative error code on error.
|
||||
*/
|
||||
int qbman_swp_set_irq_coalescing(struct qbman_swp *p, u32 irq_threshold,
|
||||
u32 irq_holdoff)
|
||||
{
|
||||
u32 itp, max_holdoff;
|
||||
|
||||
/* Convert irq_holdoff value from usecs to 256 QBMAN clock cycles
|
||||
* increments. This depends to the QBMAN internal frequency.
|
||||
*/
|
||||
itp = (irq_holdoff * 1000) / p->desc->qman_256_cycles_per_ns;
|
||||
if (itp < 0 || itp > 4096) {
|
||||
max_holdoff = (p->desc->qman_256_cycles_per_ns * 4096) / 1000;
|
||||
pr_err("irq_holdoff must be between 0..%dus\n", max_holdoff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (irq_threshold >= p->dqrr.dqrr_size || irq_threshold < 0) {
|
||||
pr_err("irq_threshold must be between 0..%d\n",
|
||||
p->dqrr.dqrr_size - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p->irq_threshold = irq_threshold;
|
||||
p->irq_holdoff = irq_holdoff;
|
||||
|
||||
qbman_write_register(p, QBMAN_CINH_SWP_DQRR_ITR, irq_threshold);
|
||||
qbman_write_register(p, QBMAN_CINH_SWP_ITPR, itp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qbman_swp_get_irq_coalescing() - Get the current IRQ coalescing parameters
|
||||
* @p: the software portal object
|
||||
* @irq_threshold: interrupt threshold (an IRQ is generated when there are more
|
||||
* DQRR entries in the portal than the threshold)
|
||||
* @irq_holdoff: interrupt holdoff (timeout) period in us
|
||||
*/
|
||||
void qbman_swp_get_irq_coalescing(struct qbman_swp *p, u32 *irq_threshold,
|
||||
u32 *irq_holdoff)
|
||||
{
|
||||
if (irq_threshold)
|
||||
*irq_threshold = p->irq_threshold;
|
||||
if (irq_holdoff)
|
||||
*irq_holdoff = p->irq_holdoff;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ struct qbman_swp_desc {
|
||||
void __iomem *cinh_bar; /* Cache-inhibited portal base address */
|
||||
u32 qman_version;
|
||||
u32 qman_clk;
|
||||
u32 qman_256_cycles_per_ns;
|
||||
};
|
||||
|
||||
#define QBMAN_SWP_INTERRUPT_EQRI 0x01
|
||||
@ -157,6 +158,10 @@ struct qbman_swp {
|
||||
} eqcr;
|
||||
|
||||
spinlock_t access_spinlock;
|
||||
|
||||
/* Interrupt coalescing */
|
||||
u32 irq_threshold;
|
||||
u32 irq_holdoff;
|
||||
};
|
||||
|
||||
/* Function pointers */
|
||||
@ -649,4 +654,10 @@ static inline const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
|
||||
return qbman_swp_dqrr_next_ptr(s);
|
||||
}
|
||||
|
||||
int qbman_swp_set_irq_coalescing(struct qbman_swp *p, u32 irq_threshold,
|
||||
u32 irq_holdoff);
|
||||
|
||||
void qbman_swp_get_irq_coalescing(struct qbman_swp *p, u32 *irq_threshold,
|
||||
u32 *irq_holdoff);
|
||||
|
||||
#endif /* __FSL_QBMAN_PORTAL_H */
|
||||
|
@ -131,4 +131,8 @@ int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
|
||||
u32 *fcnt, u32 *bcnt);
|
||||
int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid,
|
||||
u32 *num);
|
||||
|
||||
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff);
|
||||
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff);
|
||||
|
||||
#endif /* __FSL_DPAA2_IO_H */
|
||||
|
Loading…
Reference in New Issue
Block a user