Skip to content

Commit 484f910

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: fix wq config registers offset programming
DSA spec v1.1 [1] updated to include a stride size register for WQ configuration that will specify how much space is reserved for the WQ configuration register set. This change is expected to be in the final gen1 DSA hardware. Fix the driver to use WQCFG_OFFSET() for all WQ offset calculation and fixup WQCFG_OFFSET() to use the new calculated wq size. [1]: https://software.intel.com/content/www/us/en/develop/download/intel-data-streaming-accelerator-preliminary-architecture-specification.html Fixes: bfe1d56 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/160383444959.48058.14249265538404901781.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 3650b22 commit 484f910

4 files changed

Lines changed: 43 additions & 17 deletions

File tree

drivers/dma/idxd/device.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
295295
int i, wq_offset;
296296

297297
lockdep_assert_held(&idxd->dev_lock);
298-
memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
298+
memset(wq->wqcfg, 0, idxd->wqcfg_size);
299299
wq->type = IDXD_WQT_NONE;
300300
wq->size = 0;
301301
wq->group = NULL;
@@ -304,8 +304,8 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
304304
clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
305305
memset(wq->name, 0, WQ_NAME_SIZE);
306306

307-
for (i = 0; i < 8; i++) {
308-
wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
307+
for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
308+
wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
309309
iowrite32(0, idxd->reg_base + wq_offset);
310310
dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
311311
wq->id, i, wq_offset,
@@ -539,33 +539,32 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
539539
if (!wq->group)
540540
return 0;
541541

542-
memset(&wq->wqcfg, 0, sizeof(union wqcfg));
542+
memset(wq->wqcfg, 0, idxd->wqcfg_size);
543543

544544
/* byte 0-3 */
545-
wq->wqcfg.wq_size = wq->size;
545+
wq->wqcfg->wq_size = wq->size;
546546

547547
if (wq->size == 0) {
548548
dev_warn(dev, "Incorrect work queue size: 0\n");
549549
return -EINVAL;
550550
}
551551

552552
/* bytes 4-7 */
553-
wq->wqcfg.wq_thresh = wq->threshold;
553+
wq->wqcfg->wq_thresh = wq->threshold;
554554

555555
/* byte 8-11 */
556-
wq->wqcfg.priv = !!(wq->type == IDXD_WQT_KERNEL);
557-
wq->wqcfg.mode = 1;
558-
559-
wq->wqcfg.priority = wq->priority;
556+
wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
557+
wq->wqcfg->mode = 1;
558+
wq->wqcfg->priority = wq->priority;
560559

561560
/* bytes 12-15 */
562-
wq->wqcfg.max_xfer_shift = ilog2(wq->max_xfer_bytes);
563-
wq->wqcfg.max_batch_shift = ilog2(wq->max_batch_size);
561+
wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
562+
wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size);
564563

565564
dev_dbg(dev, "WQ %d CFGs\n", wq->id);
566-
for (i = 0; i < 8; i++) {
567-
wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
568-
iowrite32(wq->wqcfg.bits[i], idxd->reg_base + wq_offset);
565+
for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
566+
wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
567+
iowrite32(wq->wqcfg->bits[i], idxd->reg_base + wq_offset);
569568
dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
570569
wq->id, i, wq_offset,
571570
ioread32(idxd->reg_base + wq_offset));

drivers/dma/idxd/idxd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct idxd_wq {
103103
u32 priority;
104104
enum idxd_wq_state state;
105105
unsigned long flags;
106-
union wqcfg wqcfg;
106+
union wqcfg *wqcfg;
107107
u32 vec_ptr; /* interrupt steering */
108108
struct dsa_hw_desc **hw_descs;
109109
int num_descs;
@@ -183,6 +183,7 @@ struct idxd_device {
183183
int max_wq_size;
184184
int token_limit;
185185
int nr_tokens; /* non-reserved tokens */
186+
unsigned int wqcfg_size;
186187

187188
union sw_err_reg sw_err;
188189
wait_queue_head_t cmd_waitq;

drivers/dma/idxd/init.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ static int idxd_setup_internals(struct idxd_device *idxd)
178178
wq->idxd_cdev.minor = -1;
179179
wq->max_xfer_bytes = idxd->max_xfer_bytes;
180180
wq->max_batch_size = idxd->max_batch_size;
181+
wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL);
182+
if (!wq->wqcfg)
183+
return -ENOMEM;
181184
}
182185

183186
for (i = 0; i < idxd->max_engines; i++) {
@@ -251,6 +254,8 @@ static void idxd_read_caps(struct idxd_device *idxd)
251254
dev_dbg(dev, "total workqueue size: %u\n", idxd->max_wq_size);
252255
idxd->max_wqs = idxd->hw.wq_cap.num_wqs;
253256
dev_dbg(dev, "max workqueues: %u\n", idxd->max_wqs);
257+
idxd->wqcfg_size = 1 << (idxd->hw.wq_cap.wqcfg_size + IDXD_WQCFG_MIN);
258+
dev_dbg(dev, "wqcfg size: %u\n", idxd->wqcfg_size);
254259

255260
/* reading operation capabilities */
256261
for (i = 0; i < 4; i++) {

drivers/dma/idxd/registers.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ union wq_cap_reg {
4343
struct {
4444
u64 total_wq_size:16;
4545
u64 num_wqs:8;
46-
u64 rsvd:24;
46+
u64 wqcfg_size:4;
47+
u64 rsvd:20;
4748
u64 shared_mode:1;
4849
u64 dedicated_mode:1;
4950
u64 rsvd2:1;
@@ -55,6 +56,7 @@ union wq_cap_reg {
5556
u64 bits;
5657
} __packed;
5758
#define IDXD_WQCAP_OFFSET 0x20
59+
#define IDXD_WQCFG_MIN 5
5860

5961
union group_cap_reg {
6062
struct {
@@ -333,4 +335,23 @@ union wqcfg {
333335
};
334336
u32 bits[8];
335337
} __packed;
338+
339+
/*
340+
* This macro calculates the offset into the WQCFG register
341+
* idxd - struct idxd *
342+
* n - wq id
343+
* ofs - the index of the 32b dword for the config register
344+
*
345+
* The WQCFG register block is divided into groups per each wq. The n index
346+
* allows us to move to the register group that's for that particular wq.
347+
* Each register is 32bits. The ofs gives us the number of register to access.
348+
*/
349+
#define WQCFG_OFFSET(_idxd_dev, n, ofs) \
350+
({\
351+
typeof(_idxd_dev) __idxd_dev = (_idxd_dev); \
352+
(__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs); \
353+
})
354+
355+
#define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32))
356+
336357
#endif

0 commit comments

Comments
 (0)