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

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

[PATCH] libata-ncq: implement NCQ device configuration



Now that all NCQ related stuff are in place, implement NCQ device
configuration and bump ATA_MAX_QUEUE to 32 thus activating NCQ
support.

Original implementation is from Jens Axboe.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
parent e8ee8451
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -1251,6 +1251,28 @@ static inline u8 ata_dev_knobble(struct ata_device *dev)
	return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
}

static void ata_dev_config_ncq(struct ata_device *dev,
			       char *desc, size_t desc_sz)
{
	struct ata_port *ap = dev->ap;
	int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);

	if (!ata_id_has_ncq(dev->id)) {
		desc[0] = '\0';
		return;
	}

	if (ap->flags & ATA_FLAG_NCQ) {
		hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
		dev->flags |= ATA_DFLAG_NCQ;
	}

	if (hdepth >= ddepth)
		snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
	else
		snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
}

/**
 *	ata_dev_configure - Configure the specified ATA/ATAPI device
 *	@dev: Target device to configure
@@ -1311,6 +1333,7 @@ static int ata_dev_configure(struct ata_device *dev, int print_info)

		if (ata_id_has_lba(id)) {
			const char *lba_desc;
			char ncq_desc[20];

			lba_desc = "LBA";
			dev->flags |= ATA_DFLAG_LBA;
@@ -1319,14 +1342,17 @@ static int ata_dev_configure(struct ata_device *dev, int print_info)
				lba_desc = "LBA48";
			}

			/* config NCQ */
			ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));

			/* print device info to dmesg */
			if (print_info)
				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
					"max %s, %Lu sectors: %s\n",
					"max %s, %Lu sectors: %s %s\n",
					ata_id_major_version(id),
					ata_mode_string(xfer_mask),
					(unsigned long long)dev->n_sectors,
					lba_desc);
					lba_desc, ncq_desc);
		} else {
			/* CHS */

@@ -5675,6 +5701,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(sata_scr_valid);
+46 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <linux/libata.h>
#include <linux/hdreg.h>
@@ -684,6 +685,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
		request_queue_t *q = sdev->request_queue;
		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
	}

	if (dev->flags & ATA_DFLAG_NCQ) {
		int depth;

		depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
		depth = min(ATA_MAX_QUEUE - 1, depth);
		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
	}
}

/**
@@ -717,6 +726,43 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
	return 0;	/* scsi layer doesn't check return value, sigh */
}

/**
 *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
 *	@sdev: SCSI device to configure queue depth for
 *	@queue_depth: new queue depth
 *
 *	This is libata standard hostt->change_queue_depth callback.
 *	SCSI will call into this callback when user tries to set queue
 *	depth via sysfs.
 *
 *	LOCKING:
 *	SCSI layer (we don't care)
 *
 *	RETURNS:
 *	Newly configured queue depth.
 */
int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
	struct ata_port *ap = ata_shost_to_port(sdev->host);
	struct ata_device *dev;
	int max_depth;

	if (queue_depth < 1)
		return sdev->queue_depth;

	dev = ata_scsi_find_dev(ap, sdev);
	if (!dev || !ata_dev_enabled(dev))
		return sdev->queue_depth;

	max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
	max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
	if (queue_depth > max_depth)
		queue_depth = max_depth;

	scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
	return queue_depth;
}

/**
 *	ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
 *	@qc: Storage for translated ATA taskfile
+3 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ enum {
	ATA_MAX_PORTS		= 8,
	ATA_DEF_QUEUE		= 1,
	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
	ATA_MAX_QUEUE		= 2,
	ATA_MAX_QUEUE		= 32,
	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
	ATA_MAX_SECTORS		= 200,	/* FIXME */
	ATA_MAX_BUS		= 2,
@@ -679,6 +679,8 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
			      struct block_device *bdev,
			      sector_t capacity, int geom[]);
extern int ata_scsi_slave_config(struct scsi_device *sdev);
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
				       int queue_depth);
extern struct ata_device *ata_dev_pair(struct ata_device *adev);

/*