Commit 6037d6bb authored by Jeff Garzik's avatar Jeff Garzik

[libata] ATAPI pad allocation fixes/cleanup

Use ata_pad_{alloc,free} in two drivers, to factor out common code.

Add ata_pad_{alloc,free} to two other drivers, which needed the padding
but had not been updated.
parent c2cc87ca
...@@ -307,21 +307,22 @@ static int ahci_port_start(struct ata_port *ap) ...@@ -307,21 +307,22 @@ static int ahci_port_start(struct ata_port *ap)
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
void *mem; void *mem;
dma_addr_t mem_dma; dma_addr_t mem_dma;
int rc;
pp = kmalloc(sizeof(*pp), GFP_KERNEL); pp = kmalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) if (!pp)
return -ENOMEM; return -ENOMEM;
memset(pp, 0, sizeof(*pp)); memset(pp, 0, sizeof(*pp));
ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); rc = ata_pad_alloc(ap, dev);
if (!ap->pad) { if (rc) {
kfree(pp); kfree(pp);
return -ENOMEM; return rc;
} }
mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
if (!mem) { if (!mem) {
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); ata_pad_free(ap, dev);
kfree(pp); kfree(pp);
return -ENOMEM; return -ENOMEM;
} }
...@@ -397,7 +398,7 @@ static void ahci_port_stop(struct ata_port *ap) ...@@ -397,7 +398,7 @@ static void ahci_port_stop(struct ata_port *ap)
ap->private_data = NULL; ap->private_data = NULL;
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
pp->cmd_slot, pp->cmd_slot_dma); pp->cmd_slot, pp->cmd_slot_dma);
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); ata_pad_free(ap, dev);
kfree(pp); kfree(pp);
} }
......
...@@ -4091,15 +4091,16 @@ err_out: ...@@ -4091,15 +4091,16 @@ err_out:
int ata_port_start (struct ata_port *ap) int ata_port_start (struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
int rc;
ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
if (!ap->prd) if (!ap->prd)
return -ENOMEM; return -ENOMEM;
ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); rc = ata_pad_alloc(ap, dev);
if (!ap->pad) { if (rc) {
dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
return -ENOMEM; return rc;
} }
DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
...@@ -4125,7 +4126,7 @@ void ata_port_stop (struct ata_port *ap) ...@@ -4125,7 +4126,7 @@ void ata_port_stop (struct ata_port *ap)
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); ata_pad_free(ap, dev);
} }
void ata_host_stop (struct ata_host_set *host_set) void ata_host_stop (struct ata_host_set *host_set)
......
...@@ -670,6 +670,11 @@ static void mv_host_stop(struct ata_host_set *host_set) ...@@ -670,6 +670,11 @@ static void mv_host_stop(struct ata_host_set *host_set)
ata_host_stop(host_set); ata_host_stop(host_set);
} }
static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
{
dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
}
/** /**
* mv_port_start - Port specific init/start routine. * mv_port_start - Port specific init/start routine.
* @ap: ATA channel to manipulate * @ap: ATA channel to manipulate
...@@ -687,21 +692,23 @@ static int mv_port_start(struct ata_port *ap) ...@@ -687,21 +692,23 @@ static int mv_port_start(struct ata_port *ap)
void __iomem *port_mmio = mv_ap_base(ap); void __iomem *port_mmio = mv_ap_base(ap);
void *mem; void *mem;
dma_addr_t mem_dma; dma_addr_t mem_dma;
int rc = -ENOMEM;
pp = kmalloc(sizeof(*pp), GFP_KERNEL); pp = kmalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) { if (!pp)
return -ENOMEM; goto err_out;
}
memset(pp, 0, sizeof(*pp)); memset(pp, 0, sizeof(*pp));
mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
GFP_KERNEL); GFP_KERNEL);
if (!mem) { if (!mem)
kfree(pp); goto err_out_pp;
return -ENOMEM;
}
memset(mem, 0, MV_PORT_PRIV_DMA_SZ); memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
rc = ata_pad_alloc(ap, dev);
if (rc)
goto err_out_priv;
/* First item in chunk of DMA memory: /* First item in chunk of DMA memory:
* 32-slot command request table (CRQB), 32 bytes each in size * 32-slot command request table (CRQB), 32 bytes each in size
*/ */
...@@ -746,6 +753,13 @@ static int mv_port_start(struct ata_port *ap) ...@@ -746,6 +753,13 @@ static int mv_port_start(struct ata_port *ap)
*/ */
ap->private_data = pp; ap->private_data = pp;
return 0; return 0;
err_out_priv:
mv_priv_free(pp, dev);
err_out_pp:
kfree(pp);
err_out:
return rc;
} }
/** /**
...@@ -768,7 +782,8 @@ static void mv_port_stop(struct ata_port *ap) ...@@ -768,7 +782,8 @@ static void mv_port_stop(struct ata_port *ap)
spin_unlock_irqrestore(&ap->host_set->lock, flags); spin_unlock_irqrestore(&ap->host_set->lock, flags);
ap->private_data = NULL; ap->private_data = NULL;
dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); ata_pad_free(ap, dev);
mv_priv_free(pp, dev);
kfree(pp); kfree(pp);
} }
......
...@@ -635,6 +635,13 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * ...@@ -635,6 +635,13 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
{
const size_t cb_size = sizeof(*pp->cmd_block);
dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
}
static int sil24_port_start(struct ata_port *ap) static int sil24_port_start(struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
...@@ -642,36 +649,44 @@ static int sil24_port_start(struct ata_port *ap) ...@@ -642,36 +649,44 @@ static int sil24_port_start(struct ata_port *ap)
struct sil24_cmd_block *cb; struct sil24_cmd_block *cb;
size_t cb_size = sizeof(*cb); size_t cb_size = sizeof(*cb);
dma_addr_t cb_dma; dma_addr_t cb_dma;
int rc = -ENOMEM;
pp = kmalloc(sizeof(*pp), GFP_KERNEL); pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) if (!pp)
return -ENOMEM; goto err_out;
memset(pp, 0, sizeof(*pp));
pp->tf.command = ATA_DRDY; pp->tf.command = ATA_DRDY;
cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
if (!cb) { if (!cb)
kfree(pp); goto err_out_pp;
return -ENOMEM;
}
memset(cb, 0, cb_size); memset(cb, 0, cb_size);
rc = ata_pad_alloc(ap, dev);
if (rc)
goto err_out_pad;
pp->cmd_block = cb; pp->cmd_block = cb;
pp->cmd_block_dma = cb_dma; pp->cmd_block_dma = cb_dma;
ap->private_data = pp; ap->private_data = pp;
return 0; return 0;
err_out_pad:
sil24_cblk_free(pp, dev);
err_out_pp:
kfree(pp);
err_out:
return rc;
} }
static void sil24_port_stop(struct ata_port *ap) static void sil24_port_stop(struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
size_t cb_size = sizeof(*pp->cmd_block);
dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); sil24_cblk_free(pp, dev);
kfree(pp); kfree(pp);
} }
......
...@@ -777,4 +777,17 @@ static inline unsigned int __ac_err_mask(u8 status) ...@@ -777,4 +777,17 @@ static inline unsigned int __ac_err_mask(u8 status)
return mask; return mask;
} }
static inline int ata_pad_alloc(struct ata_port *ap, struct device *dev)
{
ap->pad_dma = 0;
ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ,
&ap->pad_dma, GFP_KERNEL);
return (ap->pad == NULL) ? -ENOMEM : 0;
}
static inline void ata_pad_free(struct ata_port *ap, struct device *dev)
{
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
}
#endif /* __LINUX_LIBATA_H__ */ #endif /* __LINUX_LIBATA_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment