Skip to content

Commit

Permalink
[libata] check for SATA async notify support
Browse files Browse the repository at this point in the history
Check to see if an ATAPI device supports Asynchronous Notification.
If so, enable it, if the host controller supports AN.

Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Kristen Carlson Accardi authored and Jeff Garzik committed Oct 12, 2007
1 parent 05d1eff commit 9f45cbd
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
53 changes: 53 additions & 0 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable);
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);

Expand Down Expand Up @@ -1987,6 +1988,22 @@ int ata_dev_configure(struct ata_device *dev)
}
dev->cdb_len = (unsigned int) rc;

/*
* check to see if this ATAPI device supports
* Asynchronous Notification
*/
if ((ap->flags & ATA_FLAG_AN) && ata_id_has_AN(id)) {
int err;
/* issue SET feature command to turn this on */
err = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
if (err)
ata_dev_printk(dev, KERN_ERR,
"unable to set AN, err %x\n",
err);
else
dev->flags |= ATA_DFLAG_AN;
}

if (ata_id_cdb_intr(dev->id)) {
dev->flags |= ATA_DFLAG_CDB_INTR;
cdb_intr_string = ", CDB intr";
Expand Down Expand Up @@ -3974,6 +3991,42 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
return err_mask;
}

/**
* ata_dev_set_AN - Issue SET FEATURES - SATA FEATURES
* @dev: Device to which command will be sent
* @enable: Whether to enable or disable the feature
*
* Issue SET FEATURES - SATA FEATURES command to device @dev
* on port @ap with sector count set to indicate Asynchronous
* Notification feature
*
* LOCKING:
* PCI/etc. bus probe sem.
*
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
static unsigned int ata_dev_set_AN(struct ata_device *dev, u8 enable)
{
struct ata_taskfile tf;
unsigned int err_mask;

/* set up set-features taskfile */
DPRINTK("set features - SATA features\n");

ata_tf_init(dev, &tf);
tf.command = ATA_CMD_SET_FEATURES;
tf.feature = enable;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_NODATA;
tf.nsect = SATA_AN;

err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);

DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}

/**
* ata_dev_init_params - Issue INIT DEV PARAMS command
* @dev: Device to which command will be sent
Expand Down
9 changes: 9 additions & 0 deletions include/linux/ata.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ enum {

SETFEATURES_SPINUP = 0x07, /* Spin-up drive */

SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */

/* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */

/* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0),
ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
Expand Down Expand Up @@ -357,6 +363,9 @@ struct ata_taskfile {
#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
#define ata_id_removeable(id) ((id)[0] & (1 << 7))
#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0))
#define ata_id_has_AN(id) \
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
((id)[78] & (1 << 5)) )
#define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
#define ata_id_has_iordy(id) ((id)[49] & (1 << 11))
#define ata_id_u32(id,n) \
Expand Down
2 changes: 2 additions & 0 deletions include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ enum {
ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
ATA_DFLAG_AN = (1 << 7), /* device supports AN */
ATA_DFLAG_CFG_MASK = (1 << 8) - 1,

ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
Expand Down Expand Up @@ -179,6 +180,7 @@ enum {
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
ATA_FLAG_AN = (1 << 18), /* controller supports AN */

/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
Expand Down

0 comments on commit 9f45cbd

Please sign in to comment.