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

Commit a234f739 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Tejun Heo
Browse files

libata: switch to dynamic allocation instead of ata_scsi_rbuf



Note of the emulated commands in the pageout/pagein path, so just do
a GFP_NOIO dynamic allocation.

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

#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,
@@ -2056,53 +2053,6 @@ 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.
@@ -2121,19 +2071,24 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
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;
	unsigned long flags;
	u8 *buf;

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

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

	kfree(buf);
}

/**
 *	ata_scsiop_inq_std - Simulate INQUIRY command
 *	@args: device IDENTIFY data / SCSI command of interest.
@@ -3363,24 +3318,17 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 *
 * Return: Number of bytes copied into sglist.
 */
static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
static ssize_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;

	WARN_ON(len > ATA_SCSI_RBUF_SIZE);

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

	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);
@@ -3390,9 +3338,9 @@ static size_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, len);
	spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);

	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf,
			cmd->device->sector_size);
	kfree(buf);
	return r;
}

@@ -3408,16 +3356,15 @@ static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
 *
 * Return: Number of bytes copied into sglist.
 */
static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num)
static ssize_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;

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

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

	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);

	r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf,
			cmd->device->sector_size);
	kfree(buf);
	return r;
}

@@ -3457,7 +3399,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
	u64 block;
	u32 n_block;
	const u32 trmax = len >> 3;
	u32 size;
	ssize_t size;
	u16 fp;
	u8 bp = 0xff;
	u8 unmap = cdb[1] & 0x8;
@@ -3508,6 +3450,8 @@ 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;

@@ -3531,6 +3475,8 @@ 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;

@@ -3569,6 +3515,10 @@ 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;
}

/**