[PATCH v2 11/30] cxlflash: Make functions static
Tomas Henzl
thenzl at redhat.com
Mon Sep 21 22:18:01 AEST 2015
On 16.9.2015 23:28, Matthew R. Ochs wrote:
> Found during code inspection, that the following functions are not
> being used outside of the file where they are defined. Make them static.
>
> int cxlflash_send_cmd(struct afu *, struct afu_cmd *);
> void cxlflash_wait_resp(struct afu *, struct afu_cmd *);
> int cxlflash_afu_reset(struct cxlflash_cfg *);
> struct afu_cmd *cxlflash_cmd_checkout(struct afu *);
> void cxlflash_cmd_checkin(struct afu_cmd *);
> void init_pcr(struct cxlflash_cfg *);
> int init_global(struct cxlflash_cfg *);
>
> Signed-off-by: Matthew R. Ochs <mrochs at linux.vnet.ibm.com>
> Signed-off-by: Manoj N. Kumar <manoj at linux.vnet.ibm.com>
> ---
> drivers/scsi/cxlflash/common.h | 5 -
> drivers/scsi/cxlflash/main.c | 1018 ++++++++++++++++++++--------------------
> 2 files changed, 509 insertions(+), 514 deletions(-)
>
> diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
> index 6e0be53..2855b09 100644
> --- a/drivers/scsi/cxlflash/common.h
> +++ b/drivers/scsi/cxlflash/common.h
> @@ -194,11 +194,6 @@ static inline u64 lun_to_lunid(u64 lun)
> return swab64(lun_id);
> }
>
> -int cxlflash_send_cmd(struct afu *, struct afu_cmd *);
> -void cxlflash_wait_resp(struct afu *, struct afu_cmd *);
> -int cxlflash_afu_reset(struct cxlflash_cfg *);
> -struct afu_cmd *cxlflash_cmd_checkout(struct afu *);
> -void cxlflash_cmd_checkin(struct afu_cmd *);
> int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8);
> void cxlflash_list_init(void);
> void cxlflash_term_global_luns(void);
> diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
> index 01b7f3e..f2f41a7 100644
> --- a/drivers/scsi/cxlflash/main.c
> +++ b/drivers/scsi/cxlflash/main.c
> @@ -36,7 +36,7 @@ MODULE_LICENSE("GPL");
>
>
> /**
> - * cxlflash_cmd_checkout() - checks out an AFU command
> + * cmd_checkout() - checks out an AFU command
> * @afu: AFU to checkout from.
> *
> * Commands are checked out in a round-robin fashion. Note that since
> @@ -47,7 +47,7 @@ MODULE_LICENSE("GPL");
> *
> * Return: The checked out command or NULL when command pool is empty.
> */
> -struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
> +static struct afu_cmd *cmd_checkout(struct afu *afu)
> {
> int k, dec = CXLFLASH_NUM_CMDS;
> struct afu_cmd *cmd;
> @@ -70,7 +70,7 @@ struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
> }
>
> /**
> - * cxlflash_cmd_checkin() - checks in an AFU command
> + * cmd_checkin() - checks in an AFU command
> * @cmd: AFU command to checkin.
> *
> * Safe to pass commands that have already been checked in. Several
> @@ -79,7 +79,7 @@ struct afu_cmd *cxlflash_cmd_checkout(struct afu *afu)
> * to avoid clobbering values in the event that the command is checked
> * out right away.
> */
> -void cxlflash_cmd_checkin(struct afu_cmd *cmd)
> +static void cmd_checkin(struct afu_cmd *cmd)
> {
> cmd->rcb.scp = NULL;
> cmd->rcb.timeout = 0;
> @@ -238,7 +238,7 @@ static void cmd_complete(struct afu_cmd *cmd)
>
> resid = cmd->sa.resid;
> cmd_is_tmf = cmd->cmd_tmf;
> - cxlflash_cmd_checkin(cmd); /* Don't use cmd after here */
> + cmd_checkin(cmd); /* Don't use cmd after here */
>
> pr_debug("%s: calling scsi_set_resid, scp=%p "
> "result=%X resid=%d\n", __func__,
> @@ -260,6 +260,146 @@ static void cmd_complete(struct afu_cmd *cmd)
> }
>
> /**
> + * context_reset() - timeout handler for AFU commands
> + * @cmd: AFU command that timed out.
> + *
> + * Sends a reset to the AFU.
> + */
> +static void context_reset(struct afu_cmd *cmd)
> +{
> + int nretry = 0;
> + u64 rrin = 0x1;
> + u64 room = 0;
> + struct afu *afu = cmd->parent;
> + ulong lock_flags;
> +
> + pr_debug("%s: cmd=%p\n", __func__, cmd);
> +
> + spin_lock_irqsave(&cmd->slock, lock_flags);
> +
> + /* Already completed? */
> + if (cmd->sa.host_use_b[0] & B_DONE) {
> + spin_unlock_irqrestore(&cmd->slock, lock_flags);
> + return;
> + }
> +
> + cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT);
> + spin_unlock_irqrestore(&cmd->slock, lock_flags);
> +
> + /*
> + * We really want to send this reset at all costs, so spread
> + * out wait time on successive retries for available room.
> + */
> + do {
> + room = readq_be(&afu->host_map->cmd_room);
> + atomic64_set(&afu->room, room);
> + if (room)
> + goto write_rrin;
> + udelay(nretry);
> + } while (nretry++ < MC_ROOM_RETRY_CNT);
> +
> + pr_err("%s: no cmd_room to send reset\n", __func__);
> + return;
> +
> +write_rrin:
> + nretry = 0;
> + writeq_be(rrin, &afu->host_map->ioarrin);
> + do {
> + rrin = readq_be(&afu->host_map->ioarrin);
> + if (rrin != 0x1)
> + break;
> + /* Double delay each time */
> + udelay(2 ^ nretry);
Double delay - isn't another operator needed?
If so, pleas add a new patch for this.
--tm
> + } while (nretry++ < MC_ROOM_RETRY_CNT);
> +}
> +
> +/**
> + * send_cmd() - sends an AFU command
> + * @afu: AFU associated with the host.
> + * @cmd: AFU command to send.
> + *
> + * Return:
> + * 0 on success or SCSI_MLQUEUE_HOST_BUSY
> + */
> +static int send_cmd(struct afu *afu, struct afu_cmd *cmd)
> +{
> + struct cxlflash_cfg *cfg = afu->parent;
> + struct device *dev = &cfg->dev->dev;
> + int nretry = 0;
> + int rc = 0;
> + u64 room;
> + long newval;
> +
> + /*
> + * This routine is used by critical users such an AFU sync and to
> + * send a task management function (TMF). Thus we want to retry a
> + * bit before returning an error. To avoid the performance penalty
> + * of MMIO, we spread the update of 'room' over multiple commands.
> + */
> +retry:
> + newval = atomic64_dec_if_positive(&afu->room);
> + if (!newval) {
> + do {
> + room = readq_be(&afu->host_map->cmd_room);
> + atomic64_set(&afu->room, room);
> + if (room)
> + goto write_ioarrin;
> + udelay(nretry);
> + } while (nretry++ < MC_ROOM_RETRY_CNT);
> +
> + dev_err(dev, "%s: no cmd_room to send 0x%X\n",
> + __func__, cmd->rcb.cdb[0]);
> +
> + goto no_room;
> + } else if (unlikely(newval < 0)) {
> + /* This should be rare. i.e. Only if two threads race and
> + * decrement before the MMIO read is done. In this case
> + * just benefit from the other thread having updated
> + * afu->room.
> + */
> + if (nretry++ < MC_ROOM_RETRY_CNT) {
> + udelay(nretry);
> + goto retry;
> + }
> +
> + goto no_room;
> + }
> +
> +write_ioarrin:
> + writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin);
> +out:
> + pr_devel("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd,
> + cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc);
> + return rc;
> +
> +no_room:
> + afu->read_room = true;
> + schedule_work(&cfg->work_q);
> + rc = SCSI_MLQUEUE_HOST_BUSY;
> + goto out;
> +}
> +
> +/**
> + * wait_resp() - polls for a response or timeout to a sent AFU command
> + * @afu: AFU associated with the host.
> + * @cmd: AFU command that was sent.
> + */
> +static void wait_resp(struct afu *afu, struct afu_cmd *cmd)
> +{
> + ulong timeout = msecs_to_jiffies(cmd->rcb.timeout * 2 * 1000);
> +
> + timeout = wait_for_completion_timeout(&cmd->cevent, timeout);
> + if (!timeout)
> + context_reset(cmd);
> +
> + if (unlikely(cmd->sa.ioasc != 0))
> + pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, "
> + "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0],
> + cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc,
> + cmd->sa.rc.fc_rc);
> +}
> +
> +/**
> * send_tmf() - sends a Task Management Function (TMF)
> * @afu: AFU to checkout from.
> * @scp: SCSI command from stack.
> @@ -280,7 +420,7 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
> ulong lock_flags;
> int rc = 0;
>
> - cmd = cxlflash_cmd_checkout(afu);
> + cmd = cmd_checkout(afu);
> if (unlikely(!cmd)) {
> pr_err("%s: could not get a free command\n", __func__);
> rc = SCSI_MLQUEUE_HOST_BUSY;
> @@ -313,9 +453,9 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
> memcpy(cmd->rcb.cdb, &tmfcmd, sizeof(tmfcmd));
>
> /* Send the command */
> - rc = cxlflash_send_cmd(afu, cmd);
> + rc = send_cmd(afu, cmd);
> if (unlikely(rc)) {
> - cxlflash_cmd_checkin(cmd);
> + cmd_checkin(cmd);
> spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
> cfg->tmf_active = false;
> spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);
> @@ -398,7 +538,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
> break;
> }
>
> - cmd = cxlflash_cmd_checkout(afu);
> + cmd = cmd_checkout(afu);
> if (unlikely(!cmd)) {
> pr_err("%s: could not get a free command\n", __func__);
> rc = SCSI_MLQUEUE_HOST_BUSY;
> @@ -438,9 +578,9 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
> memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb));
>
> /* Send the command */
> - rc = cxlflash_send_cmd(afu, cmd);
> + rc = send_cmd(afu, cmd);
> if (unlikely(rc)) {
> - cxlflash_cmd_checkin(cmd);
> + cmd_checkin(cmd);
> scsi_dma_unmap(scp);
> }
>
> @@ -449,369 +589,55 @@ out:
> }
>
> /**
> - * cxlflash_eh_device_reset_handler() - reset a single LUN
> - * @scp: SCSI command to send.
> - *
> - * Return:
> - * SUCCESS as defined in scsi/scsi.h
> - * FAILED as defined in scsi/scsi.h
> + * cxlflash_wait_for_pci_err_recovery() - wait for error recovery during probe
> + * @cxlflash: Internal structure associated with the host.
> */
> -static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
> +static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg)
> {
> - int rc = SUCCESS;
> - struct Scsi_Host *host = scp->device->host;
> - struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> - struct afu *afu = cfg->afu;
> - int rcr = 0;
> -
> - pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
> - "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
> - host->host_no, scp->device->channel,
> - scp->device->id, scp->device->lun,
> - get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
> -
> - switch (cfg->state) {
> - case STATE_NORMAL:
> - rcr = send_tmf(afu, scp, TMF_LUN_RESET);
> - if (unlikely(rcr))
> - rc = FAILED;
> - break;
> - case STATE_RESET:
> - wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
> - if (cfg->state == STATE_NORMAL)
> - break;
> - /* fall through */
> - default:
> - rc = FAILED;
> - break;
> - }
> + struct pci_dev *pdev = cfg->dev;
>
> - pr_debug("%s: returning rc=%d\n", __func__, rc);
> - return rc;
> + if (pci_channel_offline(pdev))
> + wait_event_timeout(cfg->reset_waitq,
> + !pci_channel_offline(pdev),
> + CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT);
> }
>
> /**
> - * cxlflash_eh_host_reset_handler() - reset the host adapter
> - * @scp: SCSI command from stack identifying host.
> - *
> - * Return:
> - * SUCCESS as defined in scsi/scsi.h
> - * FAILED as defined in scsi/scsi.h
> + * free_mem() - free memory associated with the AFU
> + * @cxlflash: Internal structure associated with the host.
> */
> -static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
> +static void free_mem(struct cxlflash_cfg *cfg)
> {
> - int rc = SUCCESS;
> - int rcr = 0;
> - struct Scsi_Host *host = scp->device->host;
> - struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> + int i;
> + char *buf = NULL;
> + struct afu *afu = cfg->afu;
>
> - pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
> - "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
> - host->host_no, scp->device->channel,
> - scp->device->id, scp->device->lun,
> - get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
> - get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
> + if (cfg->afu) {
> + for (i = 0; i < CXLFLASH_NUM_CMDS; i++) {
> + buf = afu->cmd[i].buf;
> + if (!((u64)buf & (PAGE_SIZE - 1)))
> + free_page((ulong)buf);
> + }
>
> - switch (cfg->state) {
> - case STATE_NORMAL:
> - cfg->state = STATE_RESET;
> - scsi_block_requests(cfg->host);
> - cxlflash_mark_contexts_error(cfg);
> - rcr = cxlflash_afu_reset(cfg);
> - if (rcr) {
> - rc = FAILED;
> - cfg->state = STATE_FAILTERM;
> - } else
> - cfg->state = STATE_NORMAL;
> - wake_up_all(&cfg->reset_waitq);
> - scsi_unblock_requests(cfg->host);
> - break;
> - case STATE_RESET:
> - wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
> - if (cfg->state == STATE_NORMAL)
> - break;
> - /* fall through */
> - default:
> - rc = FAILED;
> - break;
> + free_pages((ulong)afu, get_order(sizeof(struct afu)));
> + cfg->afu = NULL;
> }
> -
> - pr_debug("%s: returning rc=%d\n", __func__, rc);
> - return rc;
> }
>
> /**
> - * cxlflash_change_queue_depth() - change the queue depth for the device
> - * @sdev: SCSI device destined for queue depth change.
> - * @qdepth: Requested queue depth value to set.
> - *
> - * The requested queue depth is capped to the maximum supported value.
> + * stop_afu() - stops the AFU command timers and unmaps the MMIO space
> + * @cxlflash: Internal structure associated with the host.
> *
> - * Return: The actual queue depth set.
> + * Safe to call with AFU in a partially allocated/initialized state.
> */
> -static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth)
> +static void stop_afu(struct cxlflash_cfg *cfg)
> {
> + int i;
> + struct afu *afu = cfg->afu;
>
> - if (qdepth > CXLFLASH_MAX_CMDS_PER_LUN)
> - qdepth = CXLFLASH_MAX_CMDS_PER_LUN;
> -
> - scsi_change_queue_depth(sdev, qdepth);
> - return sdev->queue_depth;
> -}
> -
> -/**
> - * cxlflash_show_port_status() - queries and presents the current port status
> - * @dev: Generic device associated with the host owning the port.
> - * @attr: Device attribute representing the port.
> - * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
> - *
> - * Return: The size of the ASCII string returned in @buf.
> - */
> -static ssize_t cxlflash_show_port_status(struct device *dev,
> - struct device_attribute *attr,
> - char *buf)
> -{
> - struct Scsi_Host *shost = class_to_shost(dev);
> - struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> - struct afu *afu = cfg->afu;
> -
> - char *disp_status;
> - int rc;
> - u32 port;
> - u64 status;
> - u64 *fc_regs;
> -
> - rc = kstrtouint((attr->attr.name + 4), 10, &port);
> - if (rc || (port >= NUM_FC_PORTS))
> - return 0;
> -
> - fc_regs = &afu->afu_map->global.fc_regs[port][0];
> - status =
> - (readq_be(&fc_regs[FC_MTIP_STATUS / 8]) & FC_MTIP_STATUS_MASK);
> -
> - if (status == FC_MTIP_STATUS_ONLINE)
> - disp_status = "online";
> - else if (status == FC_MTIP_STATUS_OFFLINE)
> - disp_status = "offline";
> - else
> - disp_status = "unknown";
> -
> - return snprintf(buf, PAGE_SIZE, "%s\n", disp_status);
> -}
> -
> -/**
> - * cxlflash_show_lun_mode() - presents the current LUN mode of the host
> - * @dev: Generic device associated with the host.
> - * @attr: Device attribute representing the lun mode.
> - * @buf: Buffer of length PAGE_SIZE to report back the LUN mode in ASCII.
> - *
> - * Return: The size of the ASCII string returned in @buf.
> - */
> -static ssize_t cxlflash_show_lun_mode(struct device *dev,
> - struct device_attribute *attr, char *buf)
> -{
> - struct Scsi_Host *shost = class_to_shost(dev);
> - struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> - struct afu *afu = cfg->afu;
> -
> - return snprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun);
> -}
> -
> -/**
> - * cxlflash_store_lun_mode() - sets the LUN mode of the host
> - * @dev: Generic device associated with the host.
> - * @attr: Device attribute representing the lun mode.
> - * @buf: Buffer of length PAGE_SIZE containing the LUN mode in ASCII.
> - * @count: Length of data resizing in @buf.
> - *
> - * The CXL Flash AFU supports a dummy LUN mode where the external
> - * links and storage are not required. Space on the FPGA is used
> - * to create 1 or 2 small LUNs which are presented to the system
> - * as if they were a normal storage device. This feature is useful
> - * during development and also provides manufacturing with a way
> - * to test the AFU without an actual device.
> - *
> - * 0 = external LUN[s] (default)
> - * 1 = internal LUN (1 x 64K, 512B blocks, id 0)
> - * 2 = internal LUN (1 x 64K, 4K blocks, id 0)
> - * 3 = internal LUN (2 x 32K, 512B blocks, ids 0,1)
> - * 4 = internal LUN (2 x 32K, 4K blocks, ids 0,1)
> - *
> - * Return: The size of the ASCII string returned in @buf.
> - */
> -static ssize_t cxlflash_store_lun_mode(struct device *dev,
> - struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct Scsi_Host *shost = class_to_shost(dev);
> - struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> - struct afu *afu = cfg->afu;
> - int rc;
> - u32 lun_mode;
> -
> - rc = kstrtouint(buf, 10, &lun_mode);
> - if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
> - afu->internal_lun = lun_mode;
> - cxlflash_afu_reset(cfg);
> - scsi_scan_host(cfg->host);
> - }
> -
> - return count;
> -}
> -
> -/**
> - * cxlflash_show_ioctl_version() - presents the current ioctl version of the host
> - * @dev: Generic device associated with the host.
> - * @attr: Device attribute representing the ioctl version.
> - * @buf: Buffer of length PAGE_SIZE to report back the ioctl version.
> - *
> - * Return: The size of the ASCII string returned in @buf.
> - */
> -static ssize_t cxlflash_show_ioctl_version(struct device *dev,
> - struct device_attribute *attr,
> - char *buf)
> -{
> - return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
> -}
> -
> -/**
> - * cxlflash_show_dev_mode() - presents the current mode of the device
> - * @dev: Generic device associated with the device.
> - * @attr: Device attribute representing the device mode.
> - * @buf: Buffer of length PAGE_SIZE to report back the dev mode in ASCII.
> - *
> - * Return: The size of the ASCII string returned in @buf.
> - */
> -static ssize_t cxlflash_show_dev_mode(struct device *dev,
> - struct device_attribute *attr, char *buf)
> -{
> - struct scsi_device *sdev = to_scsi_device(dev);
> -
> - return snprintf(buf, PAGE_SIZE, "%s\n",
> - sdev->hostdata ? "superpipe" : "legacy");
> -}
> -
> -/**
> - * cxlflash_wait_for_pci_err_recovery() - wait for error recovery during probe
> - * @cxlflash: Internal structure associated with the host.
> - */
> -static void cxlflash_wait_for_pci_err_recovery(struct cxlflash_cfg *cfg)
> -{
> - struct pci_dev *pdev = cfg->dev;
> -
> - if (pci_channel_offline(pdev))
> - wait_event_timeout(cfg->reset_waitq,
> - !pci_channel_offline(pdev),
> - CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT);
> -}
> -
> -/*
> - * Host attributes
> - */
> -static DEVICE_ATTR(port0, S_IRUGO, cxlflash_show_port_status, NULL);
> -static DEVICE_ATTR(port1, S_IRUGO, cxlflash_show_port_status, NULL);
> -static DEVICE_ATTR(lun_mode, S_IRUGO | S_IWUSR, cxlflash_show_lun_mode,
> - cxlflash_store_lun_mode);
> -static DEVICE_ATTR(ioctl_version, S_IRUGO, cxlflash_show_ioctl_version, NULL);
> -
> -static struct device_attribute *cxlflash_host_attrs[] = {
> - &dev_attr_port0,
> - &dev_attr_port1,
> - &dev_attr_lun_mode,
> - &dev_attr_ioctl_version,
> - NULL
> -};
> -
> -/*
> - * Device attributes
> - */
> -static DEVICE_ATTR(mode, S_IRUGO, cxlflash_show_dev_mode, NULL);
> -
> -static struct device_attribute *cxlflash_dev_attrs[] = {
> - &dev_attr_mode,
> - NULL
> -};
> -
> -/*
> - * Host template
> - */
> -static struct scsi_host_template driver_template = {
> - .module = THIS_MODULE,
> - .name = CXLFLASH_ADAPTER_NAME,
> - .info = cxlflash_driver_info,
> - .ioctl = cxlflash_ioctl,
> - .proc_name = CXLFLASH_NAME,
> - .queuecommand = cxlflash_queuecommand,
> - .eh_device_reset_handler = cxlflash_eh_device_reset_handler,
> - .eh_host_reset_handler = cxlflash_eh_host_reset_handler,
> - .change_queue_depth = cxlflash_change_queue_depth,
> - .cmd_per_lun = 16,
> - .can_queue = CXLFLASH_MAX_CMDS,
> - .this_id = -1,
> - .sg_tablesize = SG_NONE, /* No scatter gather support. */
> - .max_sectors = CXLFLASH_MAX_SECTORS,
> - .use_clustering = ENABLE_CLUSTERING,
> - .shost_attrs = cxlflash_host_attrs,
> - .sdev_attrs = cxlflash_dev_attrs,
> -};
> -
> -/*
> - * Device dependent values
> - */
> -static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
> -
> -/*
> - * PCI device binding table
> - */
> -static struct pci_device_id cxlflash_pci_table[] = {
> - {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA,
> - PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals},
> - {}
> -};
> -
> -MODULE_DEVICE_TABLE(pci, cxlflash_pci_table);
> -
> -/**
> - * free_mem() - free memory associated with the AFU
> - * @cxlflash: Internal structure associated with the host.
> - */
> -static void free_mem(struct cxlflash_cfg *cfg)
> -{
> - int i;
> - char *buf = NULL;
> - struct afu *afu = cfg->afu;
> -
> - if (cfg->afu) {
> - for (i = 0; i < CXLFLASH_NUM_CMDS; i++) {
> - buf = afu->cmd[i].buf;
> - if (!((u64)buf & (PAGE_SIZE - 1)))
> - free_page((ulong)buf);
> - }
> -
> - free_pages((ulong)afu, get_order(sizeof(struct afu)));
> - cfg->afu = NULL;
> - }
> -}
> -
> -/**
> - * stop_afu() - stops the AFU command timers and unmaps the MMIO space
> - * @cxlflash: Internal structure associated with the host.
> - *
> - * Safe to call with AFU in a partially allocated/initialized state.
> - */
> -static void stop_afu(struct cxlflash_cfg *cfg)
> -{
> - int i;
> - struct afu *afu = cfg->afu;
> -
> - if (likely(afu)) {
> - for (i = 0; i < CXLFLASH_NUM_CMDS; i++)
> - complete(&afu->cmd[i].cevent);
> + if (likely(afu)) {
> + for (i = 0; i < CXLFLASH_NUM_CMDS; i++)
> + complete(&afu->cmd[i].cevent);
>
> if (likely(afu->afu_map)) {
> cxl_psa_unmap((void *)afu->afu_map);
> @@ -1640,67 +1466,13 @@ out:
> }
>
> /**
> - * cxlflash_context_reset() - timeout handler for AFU commands
> - * @cmd: AFU command that timed out.
> + * init_pcr() - initialize the provisioning and control registers
> + * @cxlflash: Internal structure associated with the host.
> *
> - * Sends a reset to the AFU.
> + * Also sets up fast access to the mapped registers and initializes AFU
> + * command fields that never change.
> */
> -void cxlflash_context_reset(struct afu_cmd *cmd)
> -{
> - int nretry = 0;
> - u64 rrin = 0x1;
> - u64 room = 0;
> - struct afu *afu = cmd->parent;
> - ulong lock_flags;
> -
> - pr_debug("%s: cmd=%p\n", __func__, cmd);
> -
> - spin_lock_irqsave(&cmd->slock, lock_flags);
> -
> - /* Already completed? */
> - if (cmd->sa.host_use_b[0] & B_DONE) {
> - spin_unlock_irqrestore(&cmd->slock, lock_flags);
> - return;
> - }
> -
> - cmd->sa.host_use_b[0] |= (B_DONE | B_ERROR | B_TIMEOUT);
> - spin_unlock_irqrestore(&cmd->slock, lock_flags);
> -
> - /*
> - * We really want to send this reset at all costs, so spread
> - * out wait time on successive retries for available room.
> - */
> - do {
> - room = readq_be(&afu->host_map->cmd_room);
> - atomic64_set(&afu->room, room);
> - if (room)
> - goto write_rrin;
> - udelay(nretry);
> - } while (nretry++ < MC_ROOM_RETRY_CNT);
> -
> - pr_err("%s: no cmd_room to send reset\n", __func__);
> - return;
> -
> -write_rrin:
> - nretry = 0;
> - writeq_be(rrin, &afu->host_map->ioarrin);
> - do {
> - rrin = readq_be(&afu->host_map->ioarrin);
> - if (rrin != 0x1)
> - break;
> - /* Double delay each time */
> - udelay(2 ^ nretry);
> - } while (nretry++ < MC_ROOM_RETRY_CNT);
> -}
> -
> -/**
> - * init_pcr() - initialize the provisioning and control registers
> - * @cxlflash: Internal structure associated with the host.
> - *
> - * Also sets up fast access to the mapped registers and initializes AFU
> - * command fields that never change.
> - */
> -void init_pcr(struct cxlflash_cfg *cfg)
> +static void init_pcr(struct cxlflash_cfg *cfg)
> {
> struct afu *afu = cfg->afu;
> struct sisl_ctrl_map *ctrl_map;
> @@ -1736,7 +1508,7 @@ void init_pcr(struct cxlflash_cfg *cfg)
> * init_global() - initialize AFU global registers
> * @cxlflash: Internal structure associated with the host.
> */
> -int init_global(struct cxlflash_cfg *cfg)
> +static int init_global(struct cxlflash_cfg *cfg)
> {
> struct afu *afu = cfg->afu;
> u64 wwpn[NUM_FC_PORTS]; /* wwpn of AFU ports */
> @@ -2007,92 +1779,6 @@ err1:
> }
>
> /**
> - * cxlflash_send_cmd() - sends an AFU command
> - * @afu: AFU associated with the host.
> - * @cmd: AFU command to send.
> - *
> - * Return:
> - * 0 on success
> - * -1 on failure
> - */
> -int cxlflash_send_cmd(struct afu *afu, struct afu_cmd *cmd)
> -{
> - struct cxlflash_cfg *cfg = afu->parent;
> - int nretry = 0;
> - int rc = 0;
> - u64 room;
> - long newval;
> -
> - /*
> - * This routine is used by critical users such an AFU sync and to
> - * send a task management function (TMF). Thus we want to retry a
> - * bit before returning an error. To avoid the performance penalty
> - * of MMIO, we spread the update of 'room' over multiple commands.
> - */
> -retry:
> - newval = atomic64_dec_if_positive(&afu->room);
> - if (!newval) {
> - do {
> - room = readq_be(&afu->host_map->cmd_room);
> - atomic64_set(&afu->room, room);
> - if (room)
> - goto write_ioarrin;
> - udelay(nretry);
> - } while (nretry++ < MC_ROOM_RETRY_CNT);
> -
> - pr_err("%s: no cmd_room to send 0x%X\n",
> - __func__, cmd->rcb.cdb[0]);
> -
> - goto no_room;
> - } else if (unlikely(newval < 0)) {
> - /* This should be rare. i.e. Only if two threads race and
> - * decrement before the MMIO read is done. In this case
> - * just benefit from the other thread having updated
> - * afu->room.
> - */
> - if (nretry++ < MC_ROOM_RETRY_CNT) {
> - udelay(nretry);
> - goto retry;
> - }
> -
> - goto no_room;
> - }
> -
> -write_ioarrin:
> - writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin);
> -out:
> - pr_debug("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd,
> - cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc);
> - return rc;
> -
> -no_room:
> - afu->read_room = true;
> - schedule_work(&cfg->work_q);
> - rc = SCSI_MLQUEUE_HOST_BUSY;
> - goto out;
> -}
> -
> -/**
> - * cxlflash_wait_resp() - polls for a response or timeout to a sent AFU command
> - * @afu: AFU associated with the host.
> - * @cmd: AFU command that was sent.
> - */
> -void cxlflash_wait_resp(struct afu *afu, struct afu_cmd *cmd)
> -{
> - ulong timeout = jiffies + (cmd->rcb.timeout * 2 * HZ);
> -
> - timeout = wait_for_completion_timeout(&cmd->cevent, timeout);
> - if (!timeout)
> - cxlflash_context_reset(cmd);
> -
> - if (unlikely(cmd->sa.ioasc != 0))
> - pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, "
> - "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0],
> - cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc,
> - cmd->sa.rc.fc_rc);
> -}
> -
> -/**
> * cxlflash_afu_sync() - builds and sends an AFU sync command
> * @afu: AFU associated with the host.
> * @ctx_hndl_u: Identifies context requesting sync.
> @@ -2130,7 +1816,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
>
> mutex_lock(&sync_active);
> retry:
> - cmd = cxlflash_cmd_checkout(afu);
> + cmd = cmd_checkout(afu);
> if (unlikely(!cmd)) {
> retry_cnt++;
> udelay(1000 * retry_cnt);
> @@ -2159,11 +1845,11 @@ retry:
> *((u16 *)&cmd->rcb.cdb[2]) = swab16(ctx_hndl_u);
> *((u32 *)&cmd->rcb.cdb[4]) = swab32(res_hndl_u);
>
> - rc = cxlflash_send_cmd(afu, cmd);
> + rc = send_cmd(afu, cmd);
> if (unlikely(rc))
> goto out;
>
> - cxlflash_wait_resp(afu, cmd);
> + wait_resp(afu, cmd);
>
> /* set on timeout */
> if (unlikely((cmd->sa.ioasc != 0) ||
> @@ -2172,20 +1858,20 @@ retry:
> out:
> mutex_unlock(&sync_active);
> if (cmd)
> - cxlflash_cmd_checkin(cmd);
> + cmd_checkin(cmd);
> pr_debug("%s: returning rc=%d\n", __func__, rc);
> return rc;
> }
>
> /**
> - * cxlflash_afu_reset() - resets the AFU
> - * @cxlflash: Internal structure associated with the host.
> + * afu_reset() - resets the AFU
> + * @cfg: Internal structure associated with the host.
> *
> * Return:
> * 0 on success
> * A failure value from internal services.
> */
> -int cxlflash_afu_reset(struct cxlflash_cfg *cfg)
> +static int afu_reset(struct cxlflash_cfg *cfg)
> {
> int rc = 0;
> /* Stop the context before the reset. Since the context is
> @@ -2201,6 +1887,320 @@ int cxlflash_afu_reset(struct cxlflash_cfg *cfg)
> }
>
> /**
> + * cxlflash_eh_device_reset_handler() - reset a single LUN
> + * @scp: SCSI command to send.
> + *
> + * Return:
> + * SUCCESS as defined in scsi/scsi.h
> + * FAILED as defined in scsi/scsi.h
> + */
> +static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
> +{
> + int rc = SUCCESS;
> + struct Scsi_Host *host = scp->device->host;
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> + struct afu *afu = cfg->afu;
> + int rcr = 0;
> +
> + pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
> + "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
> + host->host_no, scp->device->channel,
> + scp->device->id, scp->device->lun,
> + get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
> +
> + switch (cfg->state) {
> + case STATE_NORMAL:
> + rcr = send_tmf(afu, scp, TMF_LUN_RESET);
> + if (unlikely(rcr))
> + rc = FAILED;
> + break;
> + case STATE_RESET:
> + wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
> + if (cfg->state == STATE_NORMAL)
> + break;
> + /* fall through */
> + default:
> + rc = FAILED;
> + break;
> + }
> +
> + pr_debug("%s: returning rc=%d\n", __func__, rc);
> + return rc;
> +}
> +
> +/**
> + * cxlflash_eh_host_reset_handler() - reset the host adapter
> + * @scp: SCSI command from stack identifying host.
> + *
> + * Return:
> + * SUCCESS as defined in scsi/scsi.h
> + * FAILED as defined in scsi/scsi.h
> + */
> +static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
> +{
> + int rc = SUCCESS;
> + int rcr = 0;
> + struct Scsi_Host *host = scp->device->host;
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> +
> + pr_debug("%s: (scp=%p) %d/%d/%d/%llu "
> + "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp,
> + host->host_no, scp->device->channel,
> + scp->device->id, scp->device->lun,
> + get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
> + get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
> +
> + switch (cfg->state) {
> + case STATE_NORMAL:
> + cfg->state = STATE_RESET;
> + scsi_block_requests(cfg->host);
> + cxlflash_mark_contexts_error(cfg);
> + rcr = afu_reset(cfg);
> + if (rcr) {
> + rc = FAILED;
> + cfg->state = STATE_FAILTERM;
> + } else
> + cfg->state = STATE_NORMAL;
> + wake_up_all(&cfg->reset_waitq);
> + scsi_unblock_requests(cfg->host);
> + break;
> + case STATE_RESET:
> + wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
> + if (cfg->state == STATE_NORMAL)
> + break;
> + /* fall through */
> + default:
> + rc = FAILED;
> + break;
> + }
> +
> + pr_debug("%s: returning rc=%d\n", __func__, rc);
> + return rc;
> +}
> +
> +/**
> + * cxlflash_change_queue_depth() - change the queue depth for the device
> + * @sdev: SCSI device destined for queue depth change.
> + * @qdepth: Requested queue depth value to set.
> + *
> + * The requested queue depth is capped to the maximum supported value.
> + *
> + * Return: The actual queue depth set.
> + */
> +static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth)
> +{
> +
> + if (qdepth > CXLFLASH_MAX_CMDS_PER_LUN)
> + qdepth = CXLFLASH_MAX_CMDS_PER_LUN;
> +
> + scsi_change_queue_depth(sdev, qdepth);
> + return sdev->queue_depth;
> +}
> +
> +/**
> + * cxlflash_show_port_status() - queries and presents the current port status
> + * @dev: Generic device associated with the host owning the port.
> + * @attr: Device attribute representing the port.
> + * @buf: Buffer of length PAGE_SIZE to report back port status in ASCII.
> + *
> + * Return: The size of the ASCII string returned in @buf.
> + */
> +static ssize_t cxlflash_show_port_status(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct Scsi_Host *shost = class_to_shost(dev);
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> + struct afu *afu = cfg->afu;
> +
> + char *disp_status;
> + int rc;
> + u32 port;
> + u64 status;
> + u64 *fc_regs;
> +
> + rc = kstrtouint((attr->attr.name + 4), 10, &port);
> + if (rc || (port >= NUM_FC_PORTS))
> + return 0;
> +
> + fc_regs = &afu->afu_map->global.fc_regs[port][0];
> + status =
> + (readq_be(&fc_regs[FC_MTIP_STATUS / 8]) & FC_MTIP_STATUS_MASK);
> +
> + if (status == FC_MTIP_STATUS_ONLINE)
> + disp_status = "online";
> + else if (status == FC_MTIP_STATUS_OFFLINE)
> + disp_status = "offline";
> + else
> + disp_status = "unknown";
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", disp_status);
> +}
> +
> +/**
> + * cxlflash_show_lun_mode() - presents the current LUN mode of the host
> + * @dev: Generic device associated with the host.
> + * @attr: Device attribute representing the lun mode.
> + * @buf: Buffer of length PAGE_SIZE to report back the LUN mode in ASCII.
> + *
> + * Return: The size of the ASCII string returned in @buf.
> + */
> +static ssize_t cxlflash_show_lun_mode(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct Scsi_Host *shost = class_to_shost(dev);
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> + struct afu *afu = cfg->afu;
> +
> + return snprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun);
> +}
> +
> +/**
> + * cxlflash_store_lun_mode() - sets the LUN mode of the host
> + * @dev: Generic device associated with the host.
> + * @attr: Device attribute representing the lun mode.
> + * @buf: Buffer of length PAGE_SIZE containing the LUN mode in ASCII.
> + * @count: Length of data resizing in @buf.
> + *
> + * The CXL Flash AFU supports a dummy LUN mode where the external
> + * links and storage are not required. Space on the FPGA is used
> + * to create 1 or 2 small LUNs which are presented to the system
> + * as if they were a normal storage device. This feature is useful
> + * during development and also provides manufacturing with a way
> + * to test the AFU without an actual device.
> + *
> + * 0 = external LUN[s] (default)
> + * 1 = internal LUN (1 x 64K, 512B blocks, id 0)
> + * 2 = internal LUN (1 x 64K, 4K blocks, id 0)
> + * 3 = internal LUN (2 x 32K, 512B blocks, ids 0,1)
> + * 4 = internal LUN (2 x 32K, 4K blocks, ids 0,1)
> + *
> + * Return: The size of the ASCII string returned in @buf.
> + */
> +static ssize_t cxlflash_store_lun_mode(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct Scsi_Host *shost = class_to_shost(dev);
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata;
> + struct afu *afu = cfg->afu;
> + int rc;
> + u32 lun_mode;
> +
> + rc = kstrtouint(buf, 10, &lun_mode);
> + if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
> + afu->internal_lun = lun_mode;
> + afu_reset(cfg);
> + scsi_scan_host(cfg->host);
> + }
> +
> + return count;
> +}
> +
> +/**
> + * cxlflash_show_ioctl_version() - presents the hosts current ioctl version
> + * @dev: Generic device associated with the host.
> + * @attr: Device attribute representing the ioctl version.
> + * @buf: Buffer of length PAGE_SIZE to report back the ioctl version.
> + *
> + * Return: The size of the ASCII string returned in @buf.
> + */
> +static ssize_t cxlflash_show_ioctl_version(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
> +}
> +
> +/**
> + * cxlflash_show_dev_mode() - presents the current mode of the device
> + * @dev: Generic device associated with the device.
> + * @attr: Device attribute representing the device mode.
> + * @buf: Buffer of length PAGE_SIZE to report back the dev mode in ASCII.
> + *
> + * Return: The size of the ASCII string returned in @buf.
> + */
> +static ssize_t cxlflash_show_dev_mode(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct scsi_device *sdev = to_scsi_device(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n",
> + sdev->hostdata ? "superpipe" : "legacy");
> +}
> +
> +/*
> + * Host attributes
> + */
> +static DEVICE_ATTR(port0, S_IRUGO, cxlflash_show_port_status, NULL);
> +static DEVICE_ATTR(port1, S_IRUGO, cxlflash_show_port_status, NULL);
> +static DEVICE_ATTR(lun_mode, S_IRUGO | S_IWUSR, cxlflash_show_lun_mode,
> + cxlflash_store_lun_mode);
> +static DEVICE_ATTR(ioctl_version, S_IRUGO, cxlflash_show_ioctl_version, NULL);
> +
> +static struct device_attribute *cxlflash_host_attrs[] = {
> + &dev_attr_port0,
> + &dev_attr_port1,
> + &dev_attr_lun_mode,
> + &dev_attr_ioctl_version,
> + NULL
> +};
> +
> +/*
> + * Device attributes
> + */
> +static DEVICE_ATTR(mode, S_IRUGO, cxlflash_show_dev_mode, NULL);
> +
> +static struct device_attribute *cxlflash_dev_attrs[] = {
> + &dev_attr_mode,
> + NULL
> +};
> +
> +/*
> + * Host template
> + */
> +static struct scsi_host_template driver_template = {
> + .module = THIS_MODULE,
> + .name = CXLFLASH_ADAPTER_NAME,
> + .info = cxlflash_driver_info,
> + .ioctl = cxlflash_ioctl,
> + .proc_name = CXLFLASH_NAME,
> + .queuecommand = cxlflash_queuecommand,
> + .eh_device_reset_handler = cxlflash_eh_device_reset_handler,
> + .eh_host_reset_handler = cxlflash_eh_host_reset_handler,
> + .change_queue_depth = cxlflash_change_queue_depth,
> + .cmd_per_lun = 16,
> + .can_queue = CXLFLASH_MAX_CMDS,
> + .this_id = -1,
> + .sg_tablesize = SG_NONE, /* No scatter gather support. */
> + .max_sectors = CXLFLASH_MAX_SECTORS,
> + .use_clustering = ENABLE_CLUSTERING,
> + .shost_attrs = cxlflash_host_attrs,
> + .sdev_attrs = cxlflash_dev_attrs,
> +};
> +
> +/*
> + * Device dependent values
> + */
> +static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
> +
> +/*
> + * PCI device binding table
> + */
> +static struct pci_device_id cxlflash_pci_table[] = {
> + {PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA,
> + PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals},
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(pci, cxlflash_pci_table);
> +
> +/**
> * cxlflash_worker_thread() - work thread handler for the AFU
> * @work: Work structure contained within cxlflash associated with host.
> *
More information about the Linuxppc-dev
mailing list