ata_exec_command_pio(ap, tf);
}
-/**
- * ata_exec - issue ATA command to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Issues PIO/MMIO write to ATA command register, with proper
- * synchronization with interrupt handler / other threads.
- *
- * LOCKING:
- * Obtains host_set lock.
- */
-
-static inline void ata_exec(struct ata_port *ap, const struct ata_taskfile *tf)
-{
- unsigned long flags;
-
- DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->ops->exec_command(ap, tf);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-}
-
/**
* ata_tf_to_host - issue ATA taskfile to host controller
* @ap: port to which command is being issued
* other threads.
*
* LOCKING:
- * Obtains host_set lock.
- */
-
-static void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
-{
- ap->ops->tf_load(ap, tf);
-
- ata_exec(ap, tf);
-}
-
-/**
- * ata_tf_to_host_nolock - issue ATA taskfile to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Issues ATA taskfile register set to ATA host controller,
- * with proper synchronization with interrupt handler and
- * other threads.
- *
- * LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf)
+static inline void ata_tf_to_host(struct ata_port *ap,
+ const struct ata_taskfile *tf)
{
ap->ops->tf_load(ap, tf);
ap->ops->exec_command(ap, tf);
*
* LOCKING:
* PCI/etc. bus probe sem.
+ * Obtains host_set lock.
*
*/
static unsigned int ata_bus_edd(struct ata_port *ap)
{
struct ata_taskfile tf;
+ unsigned long flags;
/* set up execute-device-diag (bus reset) taskfile */
/* also, take interrupts to a known state (disabled) */
tf.protocol = ATA_PROT_NODATA;
/* do bus reset */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
ata_tf_to_host(ap, &tf);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
/* spec says at least 2ms. but who knows with those
* crazy ATAPI devices...
dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt,
sg->length, dir);
- if (dma_mapping_error(dma_address))
+ if (dma_mapping_error(dma_address)) {
+ /* restore sg */
+ sg->length += qc->pad_len;
return -1;
+ }
sg_dma_address(sg) = dma_address;
sg_dma_len(sg) = sg->length;
dir = qc->dma_dir;
n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir);
- if (n_elem < 1)
+ if (n_elem < 1) {
+ /* restore last sg */
+ lsg->length += qc->pad_len;
return -1;
+ }
DPRINTK("%d sg elements mapped\n", n_elem);
switch (qc->tf.protocol) {
case ATA_PROT_NODATA:
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
break;
case ATA_PROT_DMA:
case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
ata_qc_set_polling(qc);
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
ap->hsm_task_state = HSM_ST;
queue_work(ata_wq, &ap->pio_task);
break;
case ATA_PROT_ATAPI:
ata_qc_set_polling(qc);
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
queue_work(ata_wq, &ap->packet_task);
break;
case ATA_PROT_ATAPI_NODATA:
ap->flags |= ATA_FLAG_NOINTR;
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
queue_work(ata_wq, &ap->packet_task);
break;
int ata_port_start (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
+ int rc;
ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
if (!ap->prd)
return -ENOMEM;
- ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL);
- if (!ap->pad) {
+ rc = ata_pad_alloc(ap, dev);
+ if (rc) {
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);
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_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
+ ata_pad_free(ap, dev);
}
void ata_host_stop (struct ata_host_set *host_set)
host->unique_id = ata_unique_id++;
host->max_cmd_len = 12;
- scsi_assign_lock(host, &host_set->lock);
-
ap->flags = ATA_FLAG_PORT_DISABLED;
ap->id = host->unique_id;
ap->host = host;
return probe_ent;
}
-static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num)
{
struct ata_probe_ent *probe_ent;
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
if (!probe_ent)
return NULL;
if (legacy_mode) {
if (legacy_mode & (1 << 0))
- probe_ent = ata_pci_init_legacy_port(pdev, port, 0);
+ probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
if (legacy_mode & (1 << 1))
- probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1);
+ probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
} else {
if (n_ports == 2)
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);