in char/oradax.c [777:848]
static int dax_preprocess_usr_ccbs(struct dax_ctx *ctx, int idx, int nelem)
{
int i;
/*
* The user is not allowed to specify real address types in
* the CCB header. This must be enforced by the kernel before
* submitting the CCBs to HV. The only allowed values for all
* address fields are VA or IMM
*/
for (i = 0; i < nelem; i++) {
struct dax_ccb *ccbp = &ctx->ccb_buf[i];
unsigned long ca_offset;
if (ccbp->hdr.ccb_version > max_ccb_version)
return DAX_SUBMIT_ERR_CCB_INVAL;
switch (ccbp->hdr.opcode) {
case DAX_OP_SYNC_NOP:
case DAX_OP_EXTRACT:
case DAX_OP_SCAN_VALUE:
case DAX_OP_SCAN_RANGE:
case DAX_OP_TRANSLATE:
case DAX_OP_SCAN_VALUE | DAX_OP_INVERT:
case DAX_OP_SCAN_RANGE | DAX_OP_INVERT:
case DAX_OP_TRANSLATE | DAX_OP_INVERT:
case DAX_OP_SELECT:
break;
default:
return DAX_SUBMIT_ERR_CCB_INVAL;
}
if (ccbp->hdr.out_addr_type != DAX_ADDR_TYPE_VA &&
ccbp->hdr.out_addr_type != DAX_ADDR_TYPE_NONE) {
dax_dbg("invalid out_addr_type in user CCB[%d]", i);
return DAX_SUBMIT_ERR_CCB_INVAL;
}
if (ccbp->hdr.pri_addr_type != DAX_ADDR_TYPE_VA &&
ccbp->hdr.pri_addr_type != DAX_ADDR_TYPE_NONE) {
dax_dbg("invalid pri_addr_type in user CCB[%d]", i);
return DAX_SUBMIT_ERR_CCB_INVAL;
}
if (ccbp->hdr.sec_addr_type != DAX_ADDR_TYPE_VA &&
ccbp->hdr.sec_addr_type != DAX_ADDR_TYPE_NONE) {
dax_dbg("invalid sec_addr_type in user CCB[%d]", i);
return DAX_SUBMIT_ERR_CCB_INVAL;
}
if (ccbp->hdr.table_addr_type != DAX_ADDR_TYPE_VA &&
ccbp->hdr.table_addr_type != DAX_ADDR_TYPE_NONE) {
dax_dbg("invalid table_addr_type in user CCB[%d]", i);
return DAX_SUBMIT_ERR_CCB_INVAL;
}
/* set completion (real) address and address type */
ccbp->hdr.cca_addr_type = DAX_ADDR_TYPE_RA;
ca_offset = (idx + i) * sizeof(struct dax_cca);
ccbp->ca = (void *)ctx->ca_buf_ra + ca_offset;
memset(&ctx->ca_buf[idx + i], 0, sizeof(struct dax_cca));
dax_dbg("ccb[%d]=%p, ca_offset=0x%lx, compl RA=0x%llx",
i, ccbp, ca_offset, ctx->ca_buf_ra + ca_offset);
/* skip over 2nd 64 bytes of long CCB */
if (ccbp->hdr.longccb)
i++;
}
return DAX_SUBMIT_OK;
}