diff options
author | Mark Lord <mlord@pobox.com> | 2009-02-25 15:17:43 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-03-24 22:02:41 -0400 |
commit | d16ab3f633b75aac1cf42b00355cd9aa65033dcc (patch) | |
tree | ee2df8db3222f279f21e64188ff0d156aa7820a9 | |
parent | 42ed893d8011264f9945c2f54055b47c298ac53e (diff) |
[libata] sata_mv: Add a new mv_sff_check_status() function to sata_mv.
This is necessary for use with the upcoming "mv_qc_issue_fis()" patch,
but is being added separately here for easier code review.
When using command issue via the "mv_qc_issue_fis()" mechanism,
the initial ATA_BUSY bit does not show in the ATA status (shadow) register.
This can confuse libata! So here we add a hook to fake ATA_BUSY
for that situation, until the first time a BUSY, DRQ, or ERR bit is seen.
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/sata_mv.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b74af945a2fe..542e244f37ab 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -370,6 +370,7 @@ enum { | |||
370 | MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ | 370 | MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ |
371 | MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */ | 371 | MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */ |
372 | MV_PP_FLAG_DELAYED_EH = (1 << 3), /* delayed dev err handling */ | 372 | MV_PP_FLAG_DELAYED_EH = (1 << 3), /* delayed dev err handling */ |
373 | MV_PP_FLAG_FAKE_ATA_BUSY = (1 << 4), /* ignore initial ATA_DRDY */ | ||
373 | }; | 374 | }; |
374 | 375 | ||
375 | #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) | 376 | #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) |
@@ -570,6 +571,7 @@ static void mv_bmdma_setup(struct ata_queued_cmd *qc); | |||
570 | static void mv_bmdma_start(struct ata_queued_cmd *qc); | 571 | static void mv_bmdma_start(struct ata_queued_cmd *qc); |
571 | static void mv_bmdma_stop(struct ata_queued_cmd *qc); | 572 | static void mv_bmdma_stop(struct ata_queued_cmd *qc); |
572 | static u8 mv_bmdma_status(struct ata_port *ap); | 573 | static u8 mv_bmdma_status(struct ata_port *ap); |
574 | static u8 mv_sff_check_status(struct ata_port *ap); | ||
573 | 575 | ||
574 | /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below | 576 | /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below |
575 | * because we have to allow room for worst case splitting of | 577 | * because we have to allow room for worst case splitting of |
@@ -619,6 +621,7 @@ static struct ata_port_operations mv6_ops = { | |||
619 | .softreset = mv_softreset, | 621 | .softreset = mv_softreset, |
620 | .error_handler = mv_pmp_error_handler, | 622 | .error_handler = mv_pmp_error_handler, |
621 | 623 | ||
624 | .sff_check_status = mv_sff_check_status, | ||
622 | .sff_irq_clear = mv_sff_irq_clear, | 625 | .sff_irq_clear = mv_sff_irq_clear, |
623 | .check_atapi_dma = mv_check_atapi_dma, | 626 | .check_atapi_dma = mv_check_atapi_dma, |
624 | .bmdma_setup = mv_bmdma_setup, | 627 | .bmdma_setup = mv_bmdma_setup, |
@@ -1284,7 +1287,8 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) | |||
1284 | 1287 | ||
1285 | /* set up non-NCQ EDMA configuration */ | 1288 | /* set up non-NCQ EDMA configuration */ |
1286 | cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ | 1289 | cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ |
1287 | pp->pp_flags &= ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN); | 1290 | pp->pp_flags &= |
1291 | ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); | ||
1288 | 1292 | ||
1289 | if (IS_GEN_I(hpriv)) | 1293 | if (IS_GEN_I(hpriv)) |
1290 | cfg |= (1 << 8); /* enab config burst size mask */ | 1294 | cfg |= (1 << 8); /* enab config burst size mask */ |
@@ -1791,6 +1795,33 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) | |||
1791 | } | 1795 | } |
1792 | 1796 | ||
1793 | /** | 1797 | /** |
1798 | * mv_sff_check_status - fetch device status, if valid | ||
1799 | * @ap: ATA port to fetch status from | ||
1800 | * | ||
1801 | * When using command issue via mv_qc_issue_fis(), | ||
1802 | * the initial ATA_BUSY state does not show up in the | ||
1803 | * ATA status (shadow) register. This can confuse libata! | ||
1804 | * | ||
1805 | * So we have a hook here to fake ATA_BUSY for that situation, | ||
1806 | * until the first time a BUSY, DRQ, or ERR bit is seen. | ||
1807 | * | ||
1808 | * The rest of the time, it simply returns the ATA status register. | ||
1809 | */ | ||
1810 | static u8 mv_sff_check_status(struct ata_port *ap) | ||
1811 | { | ||
1812 | u8 stat = ioread8(ap->ioaddr.status_addr); | ||
1813 | struct mv_port_priv *pp = ap->private_data; | ||
1814 | |||
1815 | if (pp->pp_flags & MV_PP_FLAG_FAKE_ATA_BUSY) { | ||
1816 | if (stat & (ATA_BUSY | ATA_DRQ | ATA_ERR)) | ||
1817 | pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; | ||
1818 | else | ||
1819 | stat = ATA_BUSY; | ||
1820 | } | ||
1821 | return stat; | ||
1822 | } | ||
1823 | |||
1824 | /** | ||
1794 | * mv_qc_issue - Initiate a command to the host | 1825 | * mv_qc_issue - Initiate a command to the host |
1795 | * @qc: queued command to start | 1826 | * @qc: queued command to start |
1796 | * | 1827 | * |
@@ -1811,6 +1842,8 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) | |||
1811 | u32 in_index; | 1842 | u32 in_index; |
1812 | unsigned int port_irqs; | 1843 | unsigned int port_irqs; |
1813 | 1844 | ||
1845 | pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; /* paranoia */ | ||
1846 | |||
1814 | switch (qc->tf.protocol) { | 1847 | switch (qc->tf.protocol) { |
1815 | case ATA_PROT_DMA: | 1848 | case ATA_PROT_DMA: |
1816 | case ATA_PROT_NCQ: | 1849 | case ATA_PROT_NCQ: |
@@ -3038,6 +3071,8 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, | |||
3038 | 3071 | ||
3039 | mv_reset_channel(hpriv, mmio, ap->port_no); | 3072 | mv_reset_channel(hpriv, mmio, ap->port_no); |
3040 | pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; | 3073 | pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; |
3074 | pp->pp_flags &= | ||
3075 | ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); | ||
3041 | 3076 | ||
3042 | /* Workaround for errata FEr SATA#10 (part 2) */ | 3077 | /* Workaround for errata FEr SATA#10 (part 2) */ |
3043 | do { | 3078 | do { |