Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/jgarzik/libata-dev

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: fix ATAPI draining
  libata: update atapi_eh_request_sense() such that lbam/lbah contains buffer size
  libata-acpi: implement _GTF command filtering
  libata-acpi: improve _GTF execution error handling and reporting
  libata-acpi: improve ACPI disabling
  libata-acpi: implement dev->gtf_cache and evaluate _GTF right after _STM during resume
  libata-acpi: implement and use ata_acpi_init_gtm()
  libata-acpi: add new hooks ata_acpi_dissociate() and ata_acpi_on_disable()
  libata: ata_dev_disable() should be called from EH context
  libata: add more opcodes to ata.h
  libata: update ata_*_printk() macros such that level can be a variable
  libata-acpi: adjust constness in ata_acpi_gtm/stm() parameters
  sata_mv: improve warnings about Highpoint RocketRAID 23xx cards
  libata: add ST3160023AS / 3.42 to NCQ blacklist
  libata: clear link->eh_info.serror from ata_std_postreset()
  sata_sil: fix spurious IRQ handling
  • Loading branch information
Linus Torvalds committed Dec 18, 2007
2 parents 64396ac + 140b5e5 commit ededa4d
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 173 deletions.
387 changes: 270 additions & 117 deletions drivers/ata/libata-acpi.c

Large diffs are not rendered by default.

101 changes: 73 additions & 28 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <linux/libata.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
#include <linux/cdrom.h>

#include "libata.h"

Expand Down Expand Up @@ -622,6 +623,7 @@ void ata_dev_disable(struct ata_device *dev)
if (ata_dev_enabled(dev)) {
if (ata_msg_drv(dev->link->ap))
ata_dev_printk(dev, KERN_WARNING, "disabled\n");
ata_acpi_on_disable(dev);
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
ATA_DNXFER_QUIET);
dev->class++;
Expand Down Expand Up @@ -3923,6 +3925,7 @@ void ata_std_postreset(struct ata_link *link, unsigned int *classes)
/* clear SError */
if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
sata_scr_write(link, SCR_ERROR, serror);
link->eh_info.serror = 0;

/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
Expand Down Expand Up @@ -4149,6 +4152,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HITACHI HDS7250SASUN500G*", NULL, ATA_HORKAGE_NONCQ },
{ "HITACHI HDS7225SBSUN250G*", NULL, ATA_HORKAGE_NONCQ },
{ "ST380817AS", "3.42", ATA_HORKAGE_NONCQ },
{ "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ },

/* Blacklist entries taken from Silicon Image 3124/3132
Windows driver .inf file - also several Linux problem reports */
Expand Down Expand Up @@ -4648,6 +4652,43 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
return 0;
}

/**
* atapi_qc_may_overflow - Check whether data transfer may overflow
* @qc: ATA command in question
*
* ATAPI commands which transfer variable length data to host
* might overflow due to application error or hardare bug. This
* function checks whether overflow should be drained and ignored
* for @qc.
*
* LOCKING:
* None.
*
* RETURNS:
* 1 if @qc may overflow; otherwise, 0.
*/
static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
{
if (qc->tf.protocol != ATA_PROT_ATAPI &&
qc->tf.protocol != ATA_PROT_ATAPI_DMA)
return 0;

if (qc->tf.flags & ATA_TFLAG_WRITE)
return 0;

switch (qc->cdb[0]) {
case READ_10:
case READ_12:
case WRITE_10:
case WRITE_12:
case GPCMD_READ_CD:
case GPCMD_READ_CD_MSF:
return 0;
}

return 1;
}

/**
* ata_std_qc_defer - Check whether a qc needs to be deferred
* @qc: ATA command in question
Expand Down Expand Up @@ -5136,23 +5177,19 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
* Inherited from caller.
*
*/

static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
struct scatterlist *sg = qc->__sg;
struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
struct ata_port *ap = qc->ap;
struct ata_eh_info *ehi = &qc->dev->link->eh_info;
struct scatterlist *sg;
struct page *page;
unsigned char *buf;
unsigned int offset, count;
int no_more_sg = 0;

if (qc->curbytes + bytes >= qc->nbytes)
ap->hsm_task_state = HSM_ST_LAST;

next_sg:
if (unlikely(no_more_sg)) {
sg = qc->cursg;
if (unlikely(!sg)) {
/*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
Expand All @@ -5161,21 +5198,28 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
* - for write case, padding zero data to the device
*/
u16 pad_buf[1] = { 0 };
unsigned int words = bytes >> 1;
unsigned int i;

if (words) /* warning if bytes > 1 */
ata_dev_printk(qc->dev, KERN_WARNING,
"%u bytes trailing data\n", bytes);
if (bytes > qc->curbytes - qc->nbytes + ATAPI_MAX_DRAIN) {
ata_ehi_push_desc(ehi, "too much trailing data "
"buf=%u cur=%u bytes=%u",
qc->nbytes, qc->curbytes, bytes);
return -1;
}

for (i = 0; i < words; i++)
/* overflow is exptected for misc ATAPI commands */
if (bytes && !atapi_qc_may_overflow(qc))
ata_dev_printk(qc->dev, KERN_WARNING, "ATAPI %u bytes "
"trailing data (cdb=%02x nbytes=%u)\n",
bytes, qc->cdb[0], qc->nbytes);

for (i = 0; i < (bytes + 1) / 2; i++)
ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);

ap->hsm_task_state = HSM_ST_LAST;
return;
}
qc->curbytes += bytes;

sg = qc->cursg;
return 0;
}

page = sg_page(sg);
offset = sg->offset + qc->cursg_ofs;
Expand Down Expand Up @@ -5210,19 +5254,20 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
}

bytes -= count;
if ((count & 1) && bytes)
bytes--;
qc->curbytes += count;
qc->cursg_ofs += count;

if (qc->cursg_ofs == sg->length) {
if (qc->cursg == lsg)
no_more_sg = 1;

qc->cursg = sg_next(qc->cursg);
qc->cursg_ofs = 0;
}

if (bytes)
goto next_sg;

return 0;
}

/**
Expand Down Expand Up @@ -5265,7 +5310,8 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)

VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);

__atapi_pio_bytes(qc, bytes);
if (__atapi_pio_bytes(qc, bytes))
goto err_out;
ata_altstatus(ap); /* flush */

return;
Expand Down Expand Up @@ -7208,18 +7254,14 @@ static void ata_port_detach(struct ata_port *ap)

ata_port_wait_eh(ap);

/* EH is now guaranteed to see UNLOADING, so no new device
* will be attached. Disable all existing devices.
/* EH is now guaranteed to see UNLOADING - EH context belongs
* to us. Disable all existing devices.
*/
spin_lock_irqsave(ap->lock, flags);

ata_port_for_each_link(link, ap) {
ata_link_for_each_dev(dev, link)
ata_dev_disable(dev);
}

spin_unlock_irqrestore(ap->lock, flags);

/* Final freeze & EH. All in-flight commands are aborted. EH
* will be skipped and retrials will be terminated with bad
* target.
Expand Down Expand Up @@ -7251,6 +7293,9 @@ void ata_host_detach(struct ata_host *host)

for (i = 0; i < host->n_ports; i++)
ata_port_detach(host->ports[i]);

/* the host is dead now, dissociate ACPI */
ata_acpi_dissociate(host);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1264,8 +1264,8 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
tf.feature |= ATAPI_PKT_DMA;
} else {
tf.protocol = ATA_PROT_ATAPI;
tf.lbam = (8 * 1024) & 0xff;
tf.lbah = (8 * 1024) >> 8;
tf.lbam = SCSI_SENSE_BUFFERSIZE;
tf.lbah = 0;
}

return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
Expand Down
8 changes: 6 additions & 2 deletions drivers/ata/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,19 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
#ifdef CONFIG_ATA_ACPI
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
extern void ata_acpi_associate(struct ata_host *host);
extern void ata_acpi_dissociate(struct ata_host *host);
extern int ata_acpi_on_suspend(struct ata_port *ap);
extern void ata_acpi_on_resume(struct ata_port *ap);
extern int ata_acpi_on_devcfg(struct ata_device *adev);
extern int ata_acpi_on_devcfg(struct ata_device *dev);
extern void ata_acpi_on_disable(struct ata_device *dev);
#else
static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
static inline void ata_acpi_associate(struct ata_host *host) { }
static inline void ata_acpi_dissociate(struct ata_host *host) { }
static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
static inline void ata_acpi_on_resume(struct ata_port *ap) { }
static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
static inline void ata_acpi_on_disable(struct ata_device *dev) { }
#endif

/* libata-scsi.c */
Expand Down
30 changes: 25 additions & 5 deletions drivers/ata/sata_mv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2506,11 +2506,31 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
if (pdev->vendor == PCI_VENDOR_ID_TTI &&
(pdev->device == 0x2300 || pdev->device == 0x2310))
{
printk(KERN_WARNING "sata_mv: Highpoint RocketRAID BIOS"
" will CORRUPT DATA on attached drives when"
" configured as \"Legacy\". BEWARE!\n");
printk(KERN_WARNING "sata_mv: Use BIOS \"JBOD\" volumes"
" instead for safety.\n");
/*
* Highpoint RocketRAID PCIe 23xx series cards:
*
* Unconfigured drives are treated as "Legacy"
* by the BIOS, and it overwrites sector 8 with
* a "Lgcy" metadata block prior to Linux boot.
*
* Configured drives (RAID or JBOD) leave sector 8
* alone, but instead overwrite a high numbered
* sector for the RAID metadata. This sector can
* be determined exactly, by truncating the physical
* drive capacity to a nice even GB value.
*
* RAID metadata is at: (dev->n_sectors & ~0xfffff)
*
* Warn the user, lest they think we're just buggy.
*/
printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
" BIOS CORRUPTS DATA on all attached drives,"
" regardless of if/how they are configured."
" BEWARE!\n");
printk(KERN_WARNING DRV_NAME ": For data safety, do not"
" use sectors 8-9 on \"Legacy\" drives,"
" and avoid the final two gigabytes on"
" all RocketRAID BIOS initialized drives.\n");
}
case chip_6042:
hpriv->ops = &mv6xxx_ops;
Expand Down
18 changes: 7 additions & 11 deletions drivers/ata/sata_sil.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,23 +390,19 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
sil_scr_read(ap, SCR_ERROR, &serror);
sil_scr_write(ap, SCR_ERROR, serror);

/* Trigger hotplug and accumulate SError only if the
* port isn't already frozen. Otherwise, PHY events
* during hardreset makes controllers with broken SIEN
* repeat probing needlessly.
/* Sometimes spurious interrupts occur, double check
* it's PHYRDY CHG.
*/
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
ata_ehi_hotplugged(&ap->link.eh_info);
if (serror & SERR_PHYRDY_CHG) {
ap->link.eh_info.serror |= serror;
goto freeze;
}

goto freeze;
if (!(bmdma2 & SIL_DMA_COMPLETE))
return;
}

if (unlikely(!qc))
goto freeze;

if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) {
if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
/* this sometimes happens, just clear IRQ */
ata_chk_status(ap);
return;
Expand Down
15 changes: 15 additions & 0 deletions include/linux/ata.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ enum {
ATA_CMD_READ_LOG_EXT = 0x2f,
ATA_CMD_PMP_READ = 0xE4,
ATA_CMD_PMP_WRITE = 0xE8,
ATA_CMD_CONF_OVERLAY = 0xB1,
ATA_CMD_SEC_FREEZE_LOCK = 0xF5,

/* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10,
Expand Down Expand Up @@ -239,6 +241,19 @@ enum {
SATA_AN = 0x05, /* Asynchronous Notification */
SATA_DIPM = 0x03, /* Device Initiated Power Management */

/* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00,
ATA_SET_MAX_PASSWD = 0x01,
ATA_SET_MAX_LOCK = 0x02,
ATA_SET_MAX_UNLOCK = 0x03,
ATA_SET_MAX_FREEZE_LOCK = 0x04,

/* feature values for DEVICE CONFIGURATION OVERLAY */
ATA_DCO_RESTORE = 0xC0,
ATA_DCO_FREEZE_LOCK = 0xC1,
ATA_DCO_IDENTIFY = 0xC2,
ATA_DCO_SET = 0xC3,

/* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0),
ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
Expand Down
Loading

0 comments on commit ededa4d

Please sign in to comment.