[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: Tejun Heo <htejun@gmail.com>
This commit is contained in:
@@ -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)));
|
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
|
* ata_dev_configure - Configure the specified ATA/ATAPI device
|
||||||
* @dev: Target device to configure
|
* @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)) {
|
if (ata_id_has_lba(id)) {
|
||||||
const char *lba_desc;
|
const char *lba_desc;
|
||||||
|
char ncq_desc[20];
|
||||||
|
|
||||||
lba_desc = "LBA";
|
lba_desc = "LBA";
|
||||||
dev->flags |= ATA_DFLAG_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";
|
lba_desc = "LBA48";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* config NCQ */
|
||||||
|
ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
|
||||||
|
|
||||||
/* print device info to dmesg */
|
/* print device info to dmesg */
|
||||||
if (print_info)
|
if (print_info)
|
||||||
ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
|
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_id_major_version(id),
|
||||||
ata_mode_string(xfer_mask),
|
ata_mode_string(xfer_mask),
|
||||||
(unsigned long long)dev->n_sectors,
|
(unsigned long long)dev->n_sectors,
|
||||||
lba_desc);
|
lba_desc, ncq_desc);
|
||||||
} else {
|
} else {
|
||||||
/* CHS */
|
/* CHS */
|
||||||
|
|
||||||
@@ -5675,6 +5701,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task);
|
|||||||
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
|
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
|
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_scsi_release);
|
||||||
EXPORT_SYMBOL_GPL(ata_host_intr);
|
EXPORT_SYMBOL_GPL(ata_host_intr);
|
||||||
EXPORT_SYMBOL_GPL(sata_scr_valid);
|
EXPORT_SYMBOL_GPL(sata_scr_valid);
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
#include <scsi/scsi_eh.h>
|
#include <scsi/scsi_eh.h>
|
||||||
#include <scsi/scsi_device.h>
|
#include <scsi/scsi_device.h>
|
||||||
#include <scsi/scsi_request.h>
|
#include <scsi/scsi_request.h>
|
||||||
|
#include <scsi/scsi_tcq.h>
|
||||||
#include <scsi/scsi_transport.h>
|
#include <scsi/scsi_transport.h>
|
||||||
#include <linux/libata.h>
|
#include <linux/libata.h>
|
||||||
#include <linux/hdreg.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;
|
request_queue_t *q = sdev->request_queue;
|
||||||
blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
|
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 */
|
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
|
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
|
||||||
* @qc: Storage for translated ATA taskfile
|
* @qc: Storage for translated ATA taskfile
|
||||||
|
@@ -109,7 +109,7 @@ enum {
|
|||||||
ATA_MAX_PORTS = 8,
|
ATA_MAX_PORTS = 8,
|
||||||
ATA_DEF_QUEUE = 1,
|
ATA_DEF_QUEUE = 1,
|
||||||
/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
|
/* 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_TAG_INTERNAL = ATA_MAX_QUEUE - 1,
|
||||||
ATA_MAX_SECTORS = 200, /* FIXME */
|
ATA_MAX_SECTORS = 200, /* FIXME */
|
||||||
ATA_MAX_BUS = 2,
|
ATA_MAX_BUS = 2,
|
||||||
@@ -679,6 +679,8 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
|
|||||||
struct block_device *bdev,
|
struct block_device *bdev,
|
||||||
sector_t capacity, int geom[]);
|
sector_t capacity, int geom[]);
|
||||||
extern int ata_scsi_slave_config(struct scsi_device *sdev);
|
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);
|
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user