Skip to content

Commit

Permalink
soc: fsl: dpio: add support for irq coalescing per software portal
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
IoanaCiornei authored and davem330 committed Oct 15, 2021
1 parent 2cf0b6f commit ed1d214
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
37 changes: 37 additions & 0 deletions drivers/soc/fsl/dpio/dpio-service.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
59 changes: 59 additions & 0 deletions drivers/soc/fsl/dpio/qbman-portal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
11 changes: 11 additions & 0 deletions drivers/soc/fsl/dpio/qbman-portal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -157,6 +158,10 @@ struct qbman_swp {
} eqcr;

spinlock_t access_spinlock;

/* Interrupt coalescing */
u32 irq_threshold;
u32 irq_holdoff;
};

/* Function pointers */
Expand Down Expand Up @@ -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 */
4 changes: 4 additions & 0 deletions include/soc/fsl/dpaa2-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit ed1d214

Please sign in to comment.