lib/idxd: fix bug in crc32c with chained ops
When spdk_idxd_submit_crc32c() handles input with multiple iovs (or multiple ops are generated due to physically discontinuous buffers), the first op has the original seed, while the subsequent ops instruct the hardware to to fetch the seed from the output of the previous op (op->hw.crc32c_val): void *prev_crc; ... desc->flags |= IDXD_FLAG_FENCE | IDXD_FLAG_CRC_READ_CRC_SEED; desc->crc32c.addr = (uint64_t)prev_crc; <<< virtual addr The problem is the prev_crc is a virtual address, so the hardware (at least with no IOMMU configured) reports: DSA_COMP_HW_ERR1 spdk_idxd_process_events: Completion status 0x20 Solution: Set crc32c.addr to the physical address of the crc32c_val field in the previous desc. Since desc->completion_addr already holds the physical address of the dsa_hw_comp_record, we use this with the crc32c_val offset. Signed-off-by: Anton Eidelman <anton@lightbitslabs.com> Change-Id: I330e98c2f3fd6da5cb4fc03d0745df09a9ff0e0c Signed-off-by: Anton Eidelman <anton@lightbitslabs.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14954 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: John Kariuki <John.K.Kariuki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
c996aff28d
commit
c2c8b4ebc7
@ -980,7 +980,7 @@ spdk_idxd_submit_crc32c(struct spdk_idxd_io_channel *chan,
|
||||
uint64_t len, seg_len;
|
||||
void *src;
|
||||
size_t i;
|
||||
void *prev_crc;
|
||||
uint64_t prev_crc;
|
||||
|
||||
assert(chan != NULL);
|
||||
assert(siov != NULL);
|
||||
@ -1037,11 +1037,11 @@ spdk_idxd_submit_crc32c(struct spdk_idxd_io_channel *chan,
|
||||
desc->crc32c.seed = seed;
|
||||
} else {
|
||||
desc->flags |= IDXD_FLAG_FENCE | IDXD_FLAG_CRC_READ_CRC_SEED;
|
||||
desc->crc32c.addr = (uint64_t)prev_crc;
|
||||
desc->crc32c.addr = prev_crc;
|
||||
}
|
||||
|
||||
desc->xfer_size = seg_len;
|
||||
prev_crc = &op->hw.crc32c_val;
|
||||
prev_crc = desc->completion_addr + offsetof(struct dsa_hw_comp_record, crc32c_val);
|
||||
|
||||
len -= seg_len;
|
||||
src += seg_len;
|
||||
@ -1075,7 +1075,7 @@ spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan,
|
||||
uint64_t len, seg_len;
|
||||
struct spdk_ioviter iter;
|
||||
struct idxd_vtophys_iter vtophys_iter;
|
||||
void *prev_crc;
|
||||
uint64_t prev_crc;
|
||||
|
||||
assert(chan != NULL);
|
||||
assert(diov != NULL);
|
||||
@ -1132,11 +1132,11 @@ spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan,
|
||||
desc->crc32c.seed = seed;
|
||||
} else {
|
||||
desc->flags |= IDXD_FLAG_FENCE | IDXD_FLAG_CRC_READ_CRC_SEED;
|
||||
desc->crc32c.addr = (uint64_t)prev_crc;
|
||||
desc->crc32c.addr = prev_crc;
|
||||
}
|
||||
|
||||
desc->xfer_size = seg_len;
|
||||
prev_crc = &op->hw.crc32c_val;
|
||||
prev_crc = desc->completion_addr + offsetof(struct dsa_hw_comp_record, crc32c_val);
|
||||
|
||||
len -= seg_len;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user