Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4ae1e26 authored by Tejun Heo's avatar Tejun Heo
Browse files

Revert "libata: switch to dynamic allocation instead of ata_scsi_rbuf"



This reverts commit a234f739.

The commit tried to get rid of the shared global SCSI response buffer.
Unfortunately, it added blocking allocation to atomic path.  Revert it
for now.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Christoph Hellwig <hch@lst.de>
parent d7969f59
Loading
Loading
Loading
Loading
+86 −36
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@

#define ATA_SCSI_RBUF_SIZE	4096

static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];

typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);

static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
@@ -2053,6 +2056,53 @@ struct ata_scsi_args {
	struct scsi_cmnd	*cmd;
};

/**
 *	ata_scsi_rbuf_get - Map response buffer.
 *	@cmd: SCSI command containing buffer to be mapped.
 *	@flags: unsigned long variable to store irq enable status
 *	@copy_in: copy in from user buffer
 *
 *	Prepare buffer for simulated SCSI commands.
 *
 *	LOCKING:
 *	spin_lock_irqsave(ata_scsi_rbuf_lock) on success
 *
 *	RETURNS:
 *	Pointer to response buffer.
 */
static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
			       unsigned long *flags)
{
	spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);

	memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
	if (copy_in)
		sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
				  ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
	return ata_scsi_rbuf;
}

/**
 *	ata_scsi_rbuf_put - Unmap response buffer.
 *	@cmd: SCSI command containing buffer to be unmapped.
 *	@copy_out: copy out result
 *	@flags: @flags passed to ata_scsi_rbuf_get()
 *
 *	Returns rbuf buffer.  The result is copied to @cmd's buffer if
 *	@copy_back is true.
 *
 *	LOCKING:
 *	Unlocks ata_scsi_rbuf_lock.
 */
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
				     unsigned long *flags)
{
	if (copy_out)
		sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
				    ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
	spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
}

/**
 *	ata_scsi_rbuf_fill - wrapper for SCSI command simulators
 *	@args: device IDENTIFY data / SCSI command of interest.
@@ -2071,24 +2121,19 @@ struct ata_scsi_args {
static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
		unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
{
	u8 *rbuf;
	unsigned int rc;
	struct scsi_cmnd *cmd = args->cmd;
	u8 *buf;
	unsigned long flags;

	buf = kzalloc(ATA_SCSI_RBUF_SIZE, GFP_NOIO);
	if (!buf) {
		ata_scsi_set_sense(args->dev, cmd, NOT_READY, 0x08, 0);
		return;
	}
	rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
	rc = actor(args, rbuf);
	ata_scsi_rbuf_put(cmd, rc == 0, &flags);

	if (actor(args, buf) == 0) {
		sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
				    buf, ATA_SCSI_RBUF_SIZE);
	if (rc == 0)
		cmd->result = SAM_STAT_GOOD;
}

	kfree(buf);
}

/**
 *	ata_scsiop_inq_std - Simulate INQUIRY command
 *	@args: device IDENTIFY data / SCSI command of interest.
@@ -3318,17 +3363,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 *
 * Return: Number of bytes copied into sglist.
 */
static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
					u64 sector, u32 count)
{
	struct scsi_device *sdp = cmd->device;
	size_t len = sdp->sector_size;
	size_t r;
	__le64 *buf;
	u32 i = 0;
	unsigned long flags;

	buf = kzalloc(cmd->device->sector_size, GFP_NOFS);
	if (!buf)
		return -ENOMEM;
	WARN_ON(len > ATA_SCSI_RBUF_SIZE);

	if (len > ATA_SCSI_RBUF_SIZE)
		len = ATA_SCSI_RBUF_SIZE;

	spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
	buf = ((void *)ata_scsi_rbuf);
	memset(buf, 0, len);
	while (i < trmax) {
		u64 entry = sector |
			((u64)(count > 0xffff ? 0xffff : count) << 48);
@@ -3338,9 +3390,9 @@ static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
		count -= 0xffff;
		sector += 0xffff;
	}
	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf,
			cmd->device->sector_size);
	kfree(buf);
	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len);
	spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);

	return r;
}

@@ -3356,15 +3408,16 @@ static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
 *
 * Return: Number of bytes copied into sglist.
 */
static ssize_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba,
		u64 num)
static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num)
{
	struct scsi_device *sdp = cmd->device;
	size_t len = sdp->sector_size;
	size_t r;
	u16 *buf;
	unsigned long flags;

	buf = kzalloc(cmd->device->sector_size, GFP_NOIO);
	if (!buf)
		return -ENOMEM;
	spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
	buf = ((void *)ata_scsi_rbuf);

	put_unaligned_le16(0x0002,  &buf[0]); /* SCT_ACT_WRITE_SAME */
	put_unaligned_le16(0x0101,  &buf[1]); /* WRITE PTRN FG */
@@ -3372,9 +3425,14 @@ static ssize_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba,
	put_unaligned_le64(num,     &buf[6]);
	put_unaligned_le32(0u,      &buf[10]); /* pattern */

	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf,
			cmd->device->sector_size);
	kfree(buf);
	WARN_ON(len > ATA_SCSI_RBUF_SIZE);

	if (len > ATA_SCSI_RBUF_SIZE)
		len = ATA_SCSI_RBUF_SIZE;

	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len);
	spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);

	return r;
}

@@ -3399,7 +3457,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
	u64 block;
	u32 n_block;
	const u32 trmax = len >> 3;
	ssize_t size;
	u32 size;
	u16 fp;
	u8 bp = 0xff;
	u8 unmap = cdb[1] & 0x8;
@@ -3450,8 +3508,6 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
	 */
	if (unmap) {
		size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block);
		if (size < 0)
			goto comm_fail;
		if (size != len)
			goto invalid_param_len;

@@ -3475,8 +3531,6 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
		}
	} else {
		size = ata_format_sct_write_same(scmd, block, n_block);
		if (size < 0)
			goto comm_fail;
		if (size != len)
			goto invalid_param_len;

@@ -3515,10 +3569,6 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
	/* "Invalid command operation code" */
	ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
	return 1;
comm_fail:
	/* "Logical unit communication failure" */
	ata_scsi_set_sense(dev, scmd, NOT_READY, 0x08, 0);
	return 1;
}

/**