Skip to content

Commit ed1d214

Browse files
IoanaCiorneidavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2cf0b6f commit ed1d214

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

drivers/soc/fsl/dpio/dpio-service.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
114114
struct device *dev)
115115
{
116116
struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
117+
u32 qman_256_cycles_per_ns;
117118

118119
if (!obj)
119120
return NULL;
@@ -129,6 +130,13 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
129130
obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
130131
obj->swp_desc.qman_clk = obj->dpio_desc.qman_clk;
131132
obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
133+
134+
/* Compute how many 256 QBMAN cycles fit into one ns. This is because
135+
* the interrupt timeout period register needs to be specified in QBMAN
136+
* clock cycles in increments of 256.
137+
*/
138+
qman_256_cycles_per_ns = 256000 / (obj->swp_desc.qman_clk / 1000000);
139+
obj->swp_desc.qman_256_cycles_per_ns = qman_256_cycles_per_ns;
132140
obj->swp = qbman_swp_init(&obj->swp_desc);
133141

134142
if (!obj->swp) {
@@ -780,3 +788,32 @@ int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, u32 *num)
780788
return 0;
781789
}
782790
EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count);
791+
792+
/**
793+
* dpaa2_io_set_irq_coalescing() - Set new IRQ coalescing values
794+
* @d: the given DPIO object
795+
* @irq_holdoff: interrupt holdoff (timeout) period in us
796+
*
797+
* Return 0 for success, or negative error code on error.
798+
*/
799+
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff)
800+
{
801+
struct qbman_swp *swp = d->swp;
802+
803+
return qbman_swp_set_irq_coalescing(swp, swp->dqrr.dqrr_size - 1,
804+
irq_holdoff);
805+
}
806+
EXPORT_SYMBOL(dpaa2_io_set_irq_coalescing);
807+
808+
/**
809+
* dpaa2_io_get_irq_coalescing() - Get the current IRQ coalescing parameters
810+
* @d: the given DPIO object
811+
* @irq_holdoff: interrupt holdoff (timeout) period in us
812+
*/
813+
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff)
814+
{
815+
struct qbman_swp *swp = d->swp;
816+
817+
qbman_swp_get_irq_coalescing(swp, NULL, irq_holdoff);
818+
}
819+
EXPORT_SYMBOL(dpaa2_io_get_irq_coalescing);

drivers/soc/fsl/dpio/qbman-portal.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define QBMAN_CINH_SWP_EQCR_AM_RT 0x980
3030
#define QBMAN_CINH_SWP_RCR_AM_RT 0x9c0
3131
#define QBMAN_CINH_SWP_DQPI 0xa00
32+
#define QBMAN_CINH_SWP_DQRR_ITR 0xa80
3233
#define QBMAN_CINH_SWP_DCAP 0xac0
3334
#define QBMAN_CINH_SWP_SDQCR 0xb00
3435
#define QBMAN_CINH_SWP_EQCR_AM_RT2 0xb40
@@ -38,6 +39,7 @@
3839
#define QBMAN_CINH_SWP_IER 0xe40
3940
#define QBMAN_CINH_SWP_ISDR 0xe80
4041
#define QBMAN_CINH_SWP_IIR 0xec0
42+
#define QBMAN_CINH_SWP_ITPR 0xf40
4143

4244
/* CENA register offsets */
4345
#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)
355357
& p->eqcr.pi_ci_mask;
356358
p->eqcr.available = p->eqcr.pi_ring_size;
357359

360+
/* Initialize the software portal with a irq timeout period of 0us */
361+
qbman_swp_set_irq_coalescing(p, p->dqrr.dqrr_size - 1, 0);
362+
358363
return p;
359364
}
360365

@@ -1796,3 +1801,57 @@ u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
17961801
{
17971802
return le32_to_cpu(a->fill);
17981803
}
1804+
1805+
/**
1806+
* qbman_swp_set_irq_coalescing() - Set new IRQ coalescing values
1807+
* @p: the software portal object
1808+
* @irq_threshold: interrupt threshold
1809+
* @irq_holdoff: interrupt holdoff (timeout) period in us
1810+
*
1811+
* Return 0 for success, or negative error code on error.
1812+
*/
1813+
int qbman_swp_set_irq_coalescing(struct qbman_swp *p, u32 irq_threshold,
1814+
u32 irq_holdoff)
1815+
{
1816+
u32 itp, max_holdoff;
1817+
1818+
/* Convert irq_holdoff value from usecs to 256 QBMAN clock cycles
1819+
* increments. This depends to the QBMAN internal frequency.
1820+
*/
1821+
itp = (irq_holdoff * 1000) / p->desc->qman_256_cycles_per_ns;
1822+
if (itp < 0 || itp > 4096) {
1823+
max_holdoff = (p->desc->qman_256_cycles_per_ns * 4096) / 1000;
1824+
pr_err("irq_holdoff must be between 0..%dus\n", max_holdoff);
1825+
return -EINVAL;
1826+
}
1827+
1828+
if (irq_threshold >= p->dqrr.dqrr_size || irq_threshold < 0) {
1829+
pr_err("irq_threshold must be between 0..%d\n",
1830+
p->dqrr.dqrr_size - 1);
1831+
return -EINVAL;
1832+
}
1833+
1834+
p->irq_threshold = irq_threshold;
1835+
p->irq_holdoff = irq_holdoff;
1836+
1837+
qbman_write_register(p, QBMAN_CINH_SWP_DQRR_ITR, irq_threshold);
1838+
qbman_write_register(p, QBMAN_CINH_SWP_ITPR, itp);
1839+
1840+
return 0;
1841+
}
1842+
1843+
/**
1844+
* qbman_swp_get_irq_coalescing() - Get the current IRQ coalescing parameters
1845+
* @p: the software portal object
1846+
* @irq_threshold: interrupt threshold (an IRQ is generated when there are more
1847+
* DQRR entries in the portal than the threshold)
1848+
* @irq_holdoff: interrupt holdoff (timeout) period in us
1849+
*/
1850+
void qbman_swp_get_irq_coalescing(struct qbman_swp *p, u32 *irq_threshold,
1851+
u32 *irq_holdoff)
1852+
{
1853+
if (irq_threshold)
1854+
*irq_threshold = p->irq_threshold;
1855+
if (irq_holdoff)
1856+
*irq_holdoff = p->irq_holdoff;
1857+
}

drivers/soc/fsl/dpio/qbman-portal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct qbman_swp_desc {
2525
void __iomem *cinh_bar; /* Cache-inhibited portal base address */
2626
u32 qman_version;
2727
u32 qman_clk;
28+
u32 qman_256_cycles_per_ns;
2829
};
2930

3031
#define QBMAN_SWP_INTERRUPT_EQRI 0x01
@@ -157,6 +158,10 @@ struct qbman_swp {
157158
} eqcr;
158159

159160
spinlock_t access_spinlock;
161+
162+
/* Interrupt coalescing */
163+
u32 irq_threshold;
164+
u32 irq_holdoff;
160165
};
161166

162167
/* Function pointers */
@@ -649,4 +654,10 @@ static inline const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
649654
return qbman_swp_dqrr_next_ptr(s);
650655
}
651656

657+
int qbman_swp_set_irq_coalescing(struct qbman_swp *p, u32 irq_threshold,
658+
u32 irq_holdoff);
659+
660+
void qbman_swp_get_irq_coalescing(struct qbman_swp *p, u32 *irq_threshold,
661+
u32 *irq_holdoff);
662+
652663
#endif /* __FSL_QBMAN_PORTAL_H */

include/soc/fsl/dpaa2-io.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,8 @@ int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
131131
u32 *fcnt, u32 *bcnt);
132132
int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid,
133133
u32 *num);
134+
135+
int dpaa2_io_set_irq_coalescing(struct dpaa2_io *d, u32 irq_holdoff);
136+
void dpaa2_io_get_irq_coalescing(struct dpaa2_io *d, u32 *irq_holdoff);
137+
134138
#endif /* __FSL_DPAA2_IO_H */

0 commit comments

Comments
 (0)