diff options
-rw-r--r-- | drivers/ata/sata_mv.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b3f35a6af32b..552006853cd7 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -735,6 +735,24 @@ static inline unsigned int mv_hardport_from_port(unsigned int port) | |||
735 | return port & MV_PORT_MASK; | 735 | return port & MV_PORT_MASK; |
736 | } | 736 | } |
737 | 737 | ||
738 | /* | ||
739 | * Consolidate some rather tricky bit shift calculations. | ||
740 | * This is hot-path stuff, so not a function. | ||
741 | * Simple code, with two return values, so macro rather than inline. | ||
742 | * | ||
743 | * port is the sole input, in range 0..7. | ||
744 | * shift is one output, for use with the main_cause and main_mask registers. | ||
745 | * hardport is the other output, in range 0..3 | ||
746 | * | ||
747 | * Note that port and hardport may be the same variable in some cases. | ||
748 | */ | ||
749 | #define MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport) \ | ||
750 | { \ | ||
751 | shift = mv_hc_from_port(port) * HC_SHIFT; \ | ||
752 | hardport = mv_hardport_from_port(port); \ | ||
753 | shift += hardport * 2; \ | ||
754 | } | ||
755 | |||
738 | static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) | 756 | static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) |
739 | { | 757 | { |
740 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); | 758 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); |
@@ -2412,15 +2430,13 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, | |||
2412 | static void mv_eh_freeze(struct ata_port *ap) | 2430 | static void mv_eh_freeze(struct ata_port *ap) |
2413 | { | 2431 | { |
2414 | struct mv_host_priv *hpriv = ap->host->private_data; | 2432 | struct mv_host_priv *hpriv = ap->host->private_data; |
2415 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; | 2433 | unsigned int shift, hardport, port = ap->port_no; |
2416 | unsigned int shift; | ||
2417 | u32 main_mask; | 2434 | u32 main_mask; |
2418 | 2435 | ||
2419 | /* FIXME: handle coalescing completion events properly */ | 2436 | /* FIXME: handle coalescing completion events properly */ |
2420 | 2437 | ||
2421 | shift = ap->port_no * 2; | 2438 | mv_stop_edma(ap); |
2422 | if (hc > 0) | 2439 | MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); |
2423 | shift++; | ||
2424 | 2440 | ||
2425 | /* disable assertion of portN err, done events */ | 2441 | /* disable assertion of portN err, done events */ |
2426 | main_mask = readl(hpriv->main_mask_reg_addr); | 2442 | main_mask = readl(hpriv->main_mask_reg_addr); |
@@ -2431,28 +2447,22 @@ static void mv_eh_freeze(struct ata_port *ap) | |||
2431 | static void mv_eh_thaw(struct ata_port *ap) | 2447 | static void mv_eh_thaw(struct ata_port *ap) |
2432 | { | 2448 | { |
2433 | struct mv_host_priv *hpriv = ap->host->private_data; | 2449 | struct mv_host_priv *hpriv = ap->host->private_data; |
2434 | void __iomem *mmio = hpriv->base; | 2450 | unsigned int shift, hardport, port = ap->port_no; |
2435 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; | 2451 | void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port); |
2436 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); | ||
2437 | void __iomem *port_mmio = mv_ap_base(ap); | 2452 | void __iomem *port_mmio = mv_ap_base(ap); |
2438 | unsigned int shift, hc_port_no = ap->port_no; | ||
2439 | u32 main_mask, hc_irq_cause; | 2453 | u32 main_mask, hc_irq_cause; |
2440 | 2454 | ||
2441 | /* FIXME: handle coalescing completion events properly */ | 2455 | /* FIXME: handle coalescing completion events properly */ |
2442 | 2456 | ||
2443 | shift = ap->port_no * 2; | 2457 | MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); |
2444 | if (hc > 0) { | ||
2445 | shift++; | ||
2446 | hc_port_no -= 4; | ||
2447 | } | ||
2448 | 2458 | ||
2449 | /* clear EDMA errors on this port */ | 2459 | /* clear EDMA errors on this port */ |
2450 | writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); | 2460 | writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); |
2451 | 2461 | ||
2452 | /* clear pending irq events */ | 2462 | /* clear pending irq events */ |
2453 | hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); | 2463 | hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); |
2454 | hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hc_port_no); | 2464 | hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport); |
2455 | writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); | 2465 | writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); |
2456 | 2466 | ||
2457 | /* enable assertion of portN err, done events */ | 2467 | /* enable assertion of portN err, done events */ |
2458 | main_mask = readl(hpriv->main_mask_reg_addr); | 2468 | main_mask = readl(hpriv->main_mask_reg_addr); |