aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/cxlflash/main.c79
-rw-r--r--drivers/scsi/cxlflash/sislite.h2
2 files changed, 53 insertions, 28 deletions
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 0656dd2d3547..7732dfc099c4 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -2212,28 +2212,22 @@ static void cxlflash_schedule_async_reset(struct cxlflash_cfg *cfg)
}
/**
- * cxlflash_afu_sync() - builds and sends an AFU sync command
+ * send_afu_cmd() - builds and sends an internal AFU command
* @afu: AFU associated with the host.
- * @ctx_hndl_u: Identifies context requesting sync.
- * @res_hndl_u: Identifies resource requesting sync.
- * @mode: Type of sync to issue (lightweight, heavyweight, global).
+ * @rcb: Pre-populated IOARCB describing command to send.
*
- * The AFU can only take 1 sync command at a time. This routine enforces this
- * limitation by using a mutex to provide exclusive access to the AFU during
- * the sync. This design point requires calling threads to not be on interrupt
- * context due to the possibility of sleeping during concurrent sync operations.
+ * The AFU can only take one internal AFU command at a time. This limitation is
+ * enforced by using a mutex to provide exclusive access to the AFU during the
+ * operation. This design point requires calling threads to not be on interrupt
+ * context due to the possibility of sleeping during concurrent AFU operations.
*
- * AFU sync operations are only necessary and allowed when the device is
- * operating normally. When not operating normally, sync requests can occur as
- * part of cleaning up resources associated with an adapter prior to removal.
- * In this scenario, these requests are simply ignored (safe due to the AFU
- * going away).
+ * The command status is optionally passed back to the caller when the caller
+ * populates the IOASA field of the IOARCB with a pointer to an IOASA structure.
*
* Return:
* 0 on success, -errno on failure
*/
-int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
- res_hndl_t res_hndl_u, u8 mode)
+static int send_afu_cmd(struct afu *afu, struct sisl_ioarcb *rcb)
{
struct cxlflash_cfg *cfg = afu->parent;
struct device *dev = &cfg->dev->dev;
@@ -2263,25 +2257,15 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
retry:
memset(cmd, 0, sizeof(*cmd));
+ memcpy(&cmd->rcb, rcb, sizeof(*rcb));
INIT_LIST_HEAD(&cmd->queue);
init_completion(&cmd->cevent);
cmd->parent = afu;
cmd->hwq_index = hwq->index;
-
- dev_dbg(dev, "%s: afu=%p cmd=%p ctx=%d nretry=%d\n",
- __func__, afu, cmd, ctx_hndl_u, nretry);
-
- cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
cmd->rcb.ctx_id = hwq->ctx_hndl;
- cmd->rcb.msi = SISL_MSI_RRQ_UPDATED;
- cmd->rcb.timeout = MC_AFU_SYNC_TIMEOUT;
-
- cmd->rcb.cdb[0] = 0xC0; /* AFU Sync */
- cmd->rcb.cdb[1] = mode;
- /* The cdb is aligned, no unaligned accessors required */
- *((__be16 *)&cmd->rcb.cdb[2]) = cpu_to_be16(ctx_hndl_u);
- *((__be32 *)&cmd->rcb.cdb[4]) = cpu_to_be32(res_hndl_u);
+ dev_dbg(dev, "%s: afu=%p cmd=%p type=%02x nretry=%d\n",
+ __func__, afu, cmd, cmd->rcb.cdb[0], nretry);
rc = afu->send_cmd(afu, cmd);
if (unlikely(rc)) {
@@ -2306,6 +2290,8 @@ retry:
break;
}
+ if (rcb->ioasa)
+ *rcb->ioasa = cmd->sa;
out:
atomic_dec(&afu->cmds_active);
mutex_unlock(&sync_active);
@@ -2315,6 +2301,43 @@ out:
}
/**
+ * cxlflash_afu_sync() - builds and sends an AFU sync command
+ * @afu: AFU associated with the host.
+ * @ctx: Identifies context requesting sync.
+ * @res: Identifies resource requesting sync.
+ * @mode: Type of sync to issue (lightweight, heavyweight, global).
+ *
+ * AFU sync operations are only necessary and allowed when the device is
+ * operating normally. When not operating normally, sync requests can occur as
+ * part of cleaning up resources associated with an adapter prior to removal.
+ * In this scenario, these requests are simply ignored (safe due to the AFU
+ * going away).
+ *
+ * Return:
+ * 0 on success, -errno on failure
+ */
+int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx, res_hndl_t res, u8 mode)
+{
+ struct cxlflash_cfg *cfg = afu->parent;
+ struct device *dev = &cfg->dev->dev;
+ struct sisl_ioarcb rcb = { 0 };
+
+ dev_dbg(dev, "%s: afu=%p ctx=%u res=%u mode=%u\n",
+ __func__, afu, ctx, res, mode);
+
+ rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
+ rcb.msi = SISL_MSI_RRQ_UPDATED;
+ rcb.timeout = MC_AFU_SYNC_TIMEOUT;
+
+ rcb.cdb[0] = SISL_AFU_CMD_SYNC;
+ rcb.cdb[1] = mode;
+ put_unaligned_be16(ctx, &rcb.cdb[2]);
+ put_unaligned_be32(res, &rcb.cdb[4]);
+
+ return send_afu_cmd(afu, &rcb);
+}
+
+/**
* cxlflash_eh_abort_handler() - abort a SCSI command
* @scp: SCSI command to abort.
*
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index a768360d2fa6..483710a89781 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -72,6 +72,8 @@ struct sisl_ioarcb {
u16 timeout; /* in units specified by req_flags */
u32 rsvd1;
u8 cdb[16]; /* must be in big endian */
+#define SISL_AFU_CMD_SYNC 0xC0 /* AFU sync command */
+
union {
u64 reserved; /* Reserved for IOARRIN mode */
struct sisl_ioasa *ioasa; /* IOASA EA for SQ Mode */