diff options
author | Mark Lord <liml@rtr.ca> | 2008-04-19 15:05:50 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-25 01:25:36 -0400 |
commit | 1cfd19aeb8c8b6291a9d11143b4d8f3dac508ed4 (patch) | |
tree | 78cf6aa4b73149fede2f72ad3f5423a6d78b84d7 /drivers/ata/sata_mv.c | |
parent | f9f7fe014fc7197a5f36f9d9859cbb27c3bdd2ab (diff) |
sata_mv: simplify freeze/thaw bit-shift calculations
Introduce the MV_PORT_TO_SHIFT_AND_HARDPORT() macro,
to centralize/simplify various scattered bits of logic
for calculating bit shifts and the like.
Some of the places that do this get it wrong, too,
so consolidating the algorithm at one place will help
keep the code correct.
For now, we use the new macro in mv_eh_{freeze,thaw}.
A subsequent patch will re-use this in the interrupt handlers
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-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); |