Skip to content

Commit

Permalink
[PATCH] libata-ncq: implement NCQ device configuration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tejun Heo committed May 15, 2006
1 parent e8ee845 commit a6e6ce8
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
31 changes: 29 additions & 2 deletions drivers/scsi/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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 */

Expand Down Expand Up @@ -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);
Expand Down
46 changes: 46 additions & 0 deletions drivers/scsi/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
}
}

/**
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);

/*
Expand Down

0 comments on commit a6e6ce8

Please sign in to comment.