aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-04-19 15:05:50 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-25 01:25:36 -0400
commit1cfd19aeb8c8b6291a9d11143b4d8f3dac508ed4 (patch)
tree78cf6aa4b73149fede2f72ad3f5423a6d78b84d7 /drivers/ata
parentf9f7fe014fc7197a5f36f9d9859cbb27c3bdd2ab (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')
-rw-r--r--drivers/ata/sata_mv.c42
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
738static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) 756static 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,
2412static void mv_eh_freeze(struct ata_port *ap) 2430static 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)
2431static void mv_eh_thaw(struct ata_port *ap) 2447static 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);