Commit 8395ae05 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more SCSI updates from James Bottomley:
 "Mostly small bug fixes and small updates.

  The only things of note is a qla2xxx fix for crash on hotplug and
  timeout and the addition of a user exposed abstraction layer for
  persistent reservation error return handling (which necessitates the
  conversion of nvme.c as well as SCSI)"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: qla2xxx: Fix crash when I/O abort times out
  nvme: Convert NVMe errors to PR errors
  scsi: sd: Convert SCSI errors to PR errors
  scsi: core: Rename status_byte to sg_status_byte
  block: Add error codes for common PR failures
  scsi: sd: sd_zbc: Trace zone append emulation
  scsi: libfc: Include the correct header
parents ff75ec43 68ad8318
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -2117,11 +2117,34 @@ static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
	return nvme_submit_sync_cmd(ns->queue, c, data, 16);
}

static int nvme_sc_to_pr_err(int nvme_sc)
{
	if (nvme_is_path_error(nvme_sc))
		return PR_STS_PATH_FAILED;

	switch (nvme_sc) {
	case NVME_SC_SUCCESS:
		return PR_STS_SUCCESS;
	case NVME_SC_RESERVATION_CONFLICT:
		return PR_STS_RESERVATION_CONFLICT;
	case NVME_SC_ONCS_NOT_SUPPORTED:
		return -EOPNOTSUPP;
	case NVME_SC_BAD_ATTRIBUTES:
	case NVME_SC_INVALID_OPCODE:
	case NVME_SC_INVALID_FIELD:
	case NVME_SC_INVALID_NS:
		return -EINVAL;
	default:
		return PR_STS_IOERR;
	}
}

static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
				u64 key, u64 sa_key, u8 op)
{
	struct nvme_command c = { };
	u8 data[16] = { 0, };
	int ret;

	put_unaligned_le64(key, &data[0]);
	put_unaligned_le64(sa_key, &data[8]);
@@ -2131,8 +2154,14 @@ static int nvme_pr_command(struct block_device *bdev, u32 cdw10,

	if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
	    bdev->bd_disk->fops == &nvme_ns_head_ops)
		return nvme_send_ns_head_pr_command(bdev, &c, data);
	return nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c, data);
		ret = nvme_send_ns_head_pr_command(bdev, &c, data);
	else
		ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
					      data);
	if (ret < 0)
		return ret;

	return nvme_sc_to_pr_err(ret);
}

static int nvme_pr_register(struct block_device *bdev, u64 old,
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/rculist.h>
#include <linux/list.h>

#include <asm/unaligned.h>

+10 −4
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ static void qla24xx_abort_iocb_timeout(void *data)
	struct qla_qpair *qpair = sp->qpair;
	u32 handle;
	unsigned long flags;
	int sp_found = 0, cmdsp_found = 0;

	if (sp->cmd_sp)
		ql_dbg(ql_dbg_async, sp->vha, 0x507c,
@@ -124,18 +125,21 @@ static void qla24xx_abort_iocb_timeout(void *data)
	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
	for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) {
		if (sp->cmd_sp && (qpair->req->outstanding_cmds[handle] ==
		    sp->cmd_sp))
		    sp->cmd_sp)) {
			qpair->req->outstanding_cmds[handle] = NULL;
			cmdsp_found = 1;
		}

		/* removing the abort */
		if (qpair->req->outstanding_cmds[handle] == sp) {
			qpair->req->outstanding_cmds[handle] = NULL;
			sp_found = 1;
			break;
		}
	}
	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);

	if (sp->cmd_sp) {
	if (cmdsp_found && sp->cmd_sp) {
		/*
		 * This done function should take care of
		 * original command ref: INIT
@@ -143,9 +147,11 @@ static void qla24xx_abort_iocb_timeout(void *data)
		sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
	}

	if (sp_found) {
		abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
		sp->done(sp, QLA_OS_TIMER_EXPIRED);
	}
}

static void qla24xx_abort_sp_done(srb_t *sp, int res)
{
+1 −1
Original line number Diff line number Diff line
@@ -376,7 +376,7 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
	 * fill in all the output members
	 */
	hdr->status = scmd->result & 0xff;
	hdr->masked_status = status_byte(scmd->result);
	hdr->masked_status = sg_status_byte(scmd->result);
	hdr->msg_status = COMMAND_COMPLETE;
	hdr->host_status = host_byte(scmd->result);
	hdr->driver_status = 0;
+34 −1
Original line number Diff line number Diff line
@@ -1709,6 +1709,36 @@ static char sd_pr_type(enum pr_type type)
	}
};

static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
{
	switch (host_byte(result)) {
	case DID_TRANSPORT_MARGINAL:
	case DID_TRANSPORT_DISRUPTED:
	case DID_BUS_BUSY:
		return PR_STS_RETRY_PATH_FAILURE;
	case DID_NO_CONNECT:
		return PR_STS_PATH_FAILED;
	case DID_TRANSPORT_FAILFAST:
		return PR_STS_PATH_FAST_FAILED;
	}

	switch (status_byte(result)) {
	case SAM_STAT_RESERVATION_CONFLICT:
		return PR_STS_RESERVATION_CONFLICT;
	case SAM_STAT_CHECK_CONDITION:
		if (!scsi_sense_valid(sshdr))
			return PR_STS_IOERR;

		if (sshdr->sense_key == ILLEGAL_REQUEST &&
		    (sshdr->asc == 0x26 || sshdr->asc == 0x24))
			return -EINVAL;

		fallthrough;
	default:
		return PR_STS_IOERR;
	}
}

static int sd_pr_command(struct block_device *bdev, u8 sa,
		u64 key, u64 sa_key, u8 type, u8 flags)
{
@@ -1737,7 +1767,10 @@ static int sd_pr_command(struct block_device *bdev, u8 sa,
		scsi_print_sense_hdr(sdev, NULL, &sshdr);
	}

	if (result <= 0)
		return result;

	return sd_scsi_to_pr_err(&sshdr, result);
}

static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
Loading