Commit fff42598 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/spare/repo/linux-2.6.7

into pobox.com:/spare/repo/libata-2.6
parents adf791bd 2b13abe5
...@@ -138,7 +138,7 @@ static struct ata_port_operations piix_pata_ops = { ...@@ -138,7 +138,7 @@ static struct ata_port_operations piix_pata_ops = {
.bmdma_setup = ata_bmdma_setup_pio, .bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio, .bmdma_start = ata_bmdma_start_pio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
...@@ -161,7 +161,7 @@ static struct ata_port_operations piix_sata_ops = { ...@@ -161,7 +161,7 @@ static struct ata_port_operations piix_sata_ops = {
.bmdma_setup = ata_bmdma_setup_pio, .bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio, .bmdma_start = ata_bmdma_start_pio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
......
...@@ -50,7 +50,6 @@ static unsigned int ata_busy_sleep (struct ata_port *ap, ...@@ -50,7 +50,6 @@ static unsigned int ata_busy_sleep (struct ata_port *ap,
unsigned long tmout_pat, unsigned long tmout_pat,
unsigned long tmout); unsigned long tmout);
static void __ata_dev_select (struct ata_port *ap, unsigned int device); static void __ata_dev_select (struct ata_port *ap, unsigned int device);
static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat);
static void ata_host_set_pio(struct ata_port *ap); static void ata_host_set_pio(struct ata_port *ap);
static void ata_host_set_udma(struct ata_port *ap); static void ata_host_set_udma(struct ata_port *ap);
static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
...@@ -65,37 +64,6 @@ MODULE_AUTHOR("Jeff Garzik"); ...@@ -65,37 +64,6 @@ MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static const char * thr_state_name[] = {
"THR_UNKNOWN",
"THR_PORT_RESET",
"THR_AWAIT_DEATH",
"THR_PROBE_FAILED",
"THR_IDLE",
"THR_PROBE_SUCCESS",
"THR_PROBE_START",
};
/**
* ata_thr_state_name - convert thread state enum to string
* @thr_state: thread state to be converted to string
*
* Converts the specified thread state id to a constant C string.
*
* LOCKING:
* None.
*
* RETURNS:
* The THR_xxx-prefixed string naming the specified thread
* state id, or the string "<invalid THR_xxx state>".
*/
static const char *ata_thr_state_name(unsigned int thr_state)
{
if (thr_state < ARRAY_SIZE(thr_state_name))
return thr_state_name[thr_state];
return "<invalid THR_xxx state>";
}
/** /**
* ata_tf_load_pio - send taskfile registers to host controller * ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent * @ap: Port to which output is sent
...@@ -1150,13 +1118,16 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ...@@ -1150,13 +1118,16 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
} }
/** /**
* ata_port_reset - * ata_bus_probe - Reset and probe ATA bus
* @ap: * @ap: Bus to probe
* *
* LOCKING: * LOCKING:
*
* RETURNS:
* Zero on success, non-zero on error.
*/ */
static void ata_port_reset(struct ata_port *ap) static int ata_bus_probe(struct ata_port *ap)
{ {
unsigned int i, found = 0; unsigned int i, found = 0;
...@@ -1180,14 +1151,12 @@ static void ata_port_reset(struct ata_port *ap) ...@@ -1180,14 +1151,12 @@ static void ata_port_reset(struct ata_port *ap)
if (ap->flags & ATA_FLAG_PORT_DISABLED) if (ap->flags & ATA_FLAG_PORT_DISABLED)
goto err_out_disable; goto err_out_disable;
ap->thr_state = THR_PROBE_SUCCESS; return 0;
return;
err_out_disable: err_out_disable:
ap->ops->port_disable(ap); ap->ops->port_disable(ap);
err_out: err_out:
ap->thr_state = THR_PROBE_FAILED; return -1;
} }
/** /**
...@@ -1806,13 +1775,13 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) ...@@ -1806,13 +1775,13 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
} }
/** /**
* ata_fill_sg - * ata_fill_sg - Fill PCI IDE PRD table
* @qc: * @qc: Metadata associated with taskfile to be transferred
* *
* LOCKING: * LOCKING:
* *
*/ */
void ata_fill_sg(struct ata_queued_cmd *qc) static void ata_fill_sg(struct ata_queued_cmd *qc)
{ {
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
...@@ -1853,6 +1822,21 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1853,6 +1822,21 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
} }
/**
* ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_qc_prep(struct ata_queued_cmd *qc)
{
if (!(qc->flags & ATA_QCFLAG_SG))
return;
ata_fill_sg(qc);
}
/** /**
* ata_sg_setup_one - * ata_sg_setup_one -
* @qc: * @qc:
...@@ -1870,7 +1854,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1870,7 +1854,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
dma_addr_t dma_address; dma_addr_t dma_address;
assert(sg == &qc->sgent); assert(sg == &qc->sgent);
...@@ -1880,9 +1863,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1880,9 +1863,6 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
sg_dma_len(sg) = cmd->request_bufflen; sg_dma_len(sg) = cmd->request_bufflen;
if (!have_sg)
return 0;
dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer, dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer,
cmd->request_bufflen, dir); cmd->request_bufflen, dir);
if (pci_dma_mapping_error(dma_address)) if (pci_dma_mapping_error(dma_address))
...@@ -1912,22 +1892,19 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) ...@@ -1912,22 +1892,19 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct scatterlist *sg; struct scatterlist *sg;
int n_elem; int n_elem, dir;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg); VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg);
assert(cmd->use_sg > 0); assert(cmd->use_sg > 0);
sg = (struct scatterlist *)cmd->request_buffer; sg = (struct scatterlist *)cmd->request_buffer;
if (have_sg) { dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir); n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir);
if (n_elem < 1) if (n_elem < 1)
return -1; return -1;
DPRINTK("%d sg elements mapped\n", n_elem); DPRINTK("%d sg elements mapped\n", n_elem);
} else {
n_elem = cmd->use_sg;
}
qc->n_elem = n_elem; qc->n_elem = n_elem;
return 0; return 0;
...@@ -2166,7 +2143,7 @@ static void ata_pio_task(void *_data) ...@@ -2166,7 +2143,7 @@ static void ata_pio_task(void *_data)
void ata_eng_timeout(struct ata_port *ap) void ata_eng_timeout(struct ata_port *ap)
{ {
u8 host_stat, drv_stat; u8 host_stat = 0, drv_stat;
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
...@@ -2187,34 +2164,28 @@ void ata_eng_timeout(struct ata_port *ap) ...@@ -2187,34 +2164,28 @@ void ata_eng_timeout(struct ata_port *ap)
qc->scsidone = scsi_finish_command; qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
if (ap->flags & ATA_FLAG_MMIO) { case ATA_PROT_ATAPI_DMA:
void *mmio = (void *) ap->ioaddr.bmdma_addr; host_stat = ata_bmdma_status(ap);
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n", /* before we do anything else, clear DMA-Start bit */
ap->id, host_stat); ata_bmdma_stop(ap);
ata_dma_complete(qc, host_stat); /* fall through */
break;
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
ap->id, qc->tf.command, drv_stat);
ata_qc_complete(qc, drv_stat);
break;
default: default:
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); ata_altstatus(ap);
drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */
ata_bmdma_ack_irq(ap);
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat); ap->id, qc->tf.command, drv_stat, host_stat);
/* complete taskfile transaction */
ata_qc_complete(qc, drv_stat); ata_qc_complete(qc, drv_stat);
break; break;
} }
...@@ -2362,10 +2333,10 @@ int ata_qc_issue(struct ata_queued_cmd *qc) ...@@ -2362,10 +2333,10 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
if (ata_sg_setup_one(qc)) if (ata_sg_setup_one(qc))
goto err_out; goto err_out;
} }
ap->ops->fill_sg(qc);
} }
ap->ops->qc_prep(qc);
qc->ap->active_tag = qc->tag; qc->ap->active_tag = qc->tag;
qc->flags |= ATA_QCFLAG_ACTIVE; qc->flags |= ATA_QCFLAG_ACTIVE;
...@@ -2446,7 +2417,7 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) ...@@ -2446,7 +2417,7 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 host_stat, dmactl; u8 dmactl;
void *mmio = (void *) ap->ioaddr.bmdma_addr; void *mmio = (void *) ap->ioaddr.bmdma_addr;
/* load PRD table addr. */ /* load PRD table addr. */
...@@ -2460,10 +2431,6 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) ...@@ -2460,10 +2431,6 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
dmactl |= ATA_DMA_WR; dmactl |= ATA_DMA_WR;
writeb(dmactl, mmio + ATA_DMA_CMD); writeb(dmactl, mmio + ATA_DMA_CMD);
/* clear interrupt, error bits */
host_stat = readb(mmio + ATA_DMA_STATUS);
writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS);
/* issue r/w command */ /* issue r/w command */
ap->ops->exec_command(ap, &qc->tf); ap->ops->exec_command(ap, &qc->tf);
} }
...@@ -2511,7 +2478,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) ...@@ -2511,7 +2478,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 host_stat, dmactl; u8 dmactl;
/* load PRD table addr. */ /* load PRD table addr. */
outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
...@@ -2523,11 +2490,6 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) ...@@ -2523,11 +2490,6 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
dmactl |= ATA_DMA_WR; dmactl |= ATA_DMA_WR;
outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
/* clear interrupt, error bits */
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
/* issue r/w command */ /* issue r/w command */
ap->ops->exec_command(ap, &qc->tf); ap->ops->exec_command(ap, &qc->tf);
} }
...@@ -2551,50 +2513,6 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc) ...@@ -2551,50 +2513,6 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
ap->ioaddr.bmdma_addr + ATA_DMA_CMD); ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
} }
/**
* ata_dma_complete - Complete an active ATA BMDMA command
* @qc: Command to complete
* @host_stat: BMDMA status register contents
*
* LOCKING:
*/
static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat)
{
struct ata_port *ap = qc->ap;
VPRINTK("ENTER\n");
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
/* ack intr, err bits */
writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
mmio + ATA_DMA_STATUS);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
/* ack intr, err bits */
outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n",
ap->id, (u32) host_stat, (u32) ata_chk_status(ap));
/* get drive status; clear intr; complete txn */
ata_qc_complete(qc, ata_wait_idle(ap));
}
/** /**
* ata_host_intr - Handle host interrupt for given (port, task) * ata_host_intr - Handle host interrupt for given (port, task)
* @ap: Port on which interrupt arrived (possibly...) * @ap: Port on which interrupt arrived (possibly...)
...@@ -2615,46 +2533,50 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -2615,46 +2533,50 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
struct ata_queued_cmd *qc) struct ata_queued_cmd *qc)
{ {
u8 status, host_stat; u8 status, host_stat;
unsigned int handled = 0;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
/* BMDMA completion */
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
if (ap->flags & ATA_FLAG_MMIO) { /* check status of DMA engine */
void *mmio = (void *) ap->ioaddr.bmdma_addr; host_stat = ata_bmdma_status(ap);
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat); VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
if (!(host_stat & ATA_DMA_INTR)) { /* if it's not our irq... */
ap->stats.idle_irq++; if (!(host_stat & ATA_DMA_INTR))
break; goto idle_irq;
}
ata_dma_complete(qc, host_stat); /* before we do anything else, clear DMA-Start bit */
handled = 1; ata_bmdma_stop(ap);
break;
/* fall through */
/* command completion, but no data xfer */
/* FIXME: a shared interrupt _will_ cause a non-data command
* to be completed prematurely, with an error.
*
* This doesn't matter right now, since we aren't sending
* non-data commands down this pipe except in development
* situations.
*/
case ATA_PROT_ATAPI:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); /* check altstatus */
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); status = ata_altstatus(ap);
if (status & ATA_BUSY)
goto idle_irq;
/* check main status, clearing INTRQ */
status = ata_chk_status(ap);
if (unlikely(status & ATA_BUSY))
goto idle_irq;
DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status);
/* ack bmdma irq events */
ata_bmdma_ack_irq(ap);
/* complete taskfile transaction */
ata_qc_complete(qc, status); ata_qc_complete(qc, status);
handled = 1;
break; break;
default: default:
goto idle_irq;
}
return 1; /* irq handled */
idle_irq:
ap->stats.idle_irq++; ap->stats.idle_irq++;
#ifdef ATA_IRQ_TRAP #ifdef ATA_IRQ_TRAP
...@@ -2664,10 +2586,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -2664,10 +2586,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
printk(KERN_WARNING "ata%d: irq trap\n", ap->id); printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
} }
#endif #endif
break; return 0; /* irq not handled */
}
return handled;
} }
/** /**
...@@ -2701,7 +2620,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ...@@ -2701,7 +2620,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) if (qc && (!(qc->tf.ctl & ATA_NIEN)))
handled += ata_host_intr(ap, qc); handled |= ata_host_intr(ap, qc);
} }
} }
...@@ -2710,62 +2629,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ...@@ -2710,62 +2629,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
/**
* ata_thread_iter -
* @ap:
*
* LOCKING:
*
* RETURNS:
*
*/
static unsigned long ata_thread_iter(struct ata_port *ap)
{
long timeout = 0;
DPRINTK("ata%u: thr_state %s\n",
ap->id, ata_thr_state_name(ap->thr_state));
switch (ap->thr_state) {
case THR_UNKNOWN:
ap->thr_state = THR_PORT_RESET;
break;
case THR_PROBE_START:
ap->thr_state = THR_PORT_RESET;
break;
case THR_PORT_RESET:
ata_port_reset(ap);
break;
case THR_PROBE_SUCCESS:
up(&ap->probe_sem);
ap->thr_state = THR_IDLE;
break;
case THR_PROBE_FAILED:
up(&ap->probe_sem);
ap->thr_state = THR_AWAIT_DEATH;
break;
case THR_AWAIT_DEATH:
case THR_IDLE:
timeout = -1;
break;
default:
printk(KERN_DEBUG "ata%u: unknown thr state %s\n",
ap->id, ata_thr_state_name(ap->thr_state));
break;
}
DPRINTK("ata%u: new thr_state %s, returning %ld\n",
ap->id, ata_thr_state_name(ap->thr_state), timeout);
return timeout;
}
/** /**
* atapi_packet_task - Write CDB bytes to hardware * atapi_packet_task - Write CDB bytes to hardware
* @_data: Port to which ATAPI device is attached. * @_data: Port to which ATAPI device is attached.
...@@ -2847,21 +2710,6 @@ void ata_port_stop (struct ata_port *ap) ...@@ -2847,21 +2710,6 @@ void ata_port_stop (struct ata_port *ap)
pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
} }
static void ata_probe_task(void *_data)
{
struct ata_port *ap = _data;
long timeout;
timeout = ata_thread_iter(ap);
if (timeout < 0)
return;
if (timeout > 0)
queue_delayed_work(ata_wq, &ap->probe_task, timeout);
else
queue_work(ata_wq, &ap->probe_task);
}
/** /**
* ata_host_remove - Unregister SCSI host structure with upper layers * ata_host_remove - Unregister SCSI host structure with upper layers
* @ap: Port to unregister * @ap: Port to unregister
...@@ -2918,7 +2766,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ...@@ -2918,7 +2766,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
ap->udma_mask = ent->udma_mask; ap->udma_mask = ent->udma_mask;
ap->flags |= ent->host_flags; ap->flags |= ent->host_flags;
ap->ops = ent->port_ops; ap->ops = ent->port_ops;
ap->thr_state = THR_PROBE_START;
ap->cbl = ATA_CBL_NONE; ap->cbl = ATA_CBL_NONE;
ap->device[0].flags = ATA_DFLAG_MASTER; ap->device[0].flags = ATA_DFLAG_MASTER;
ap->active_tag = ATA_TAG_POISON; ap->active_tag = ATA_TAG_POISON;
...@@ -2926,13 +2773,10 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ...@@ -2926,13 +2773,10 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
INIT_WORK(&ap->pio_task, ata_pio_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap);
INIT_WORK(&ap->probe_task, ata_probe_task, ap);
for (i = 0; i < ATA_MAX_DEVICES; i++) for (i = 0; i < ATA_MAX_DEVICES; i++)
ap->device[i].devno = i; ap->device[i].devno = i;
init_MUTEX_LOCKED(&ap->probe_sem);
#ifdef ATA_IRQ_TRAP #ifdef ATA_IRQ_TRAP
ap->stats.unhandled_irq = 1; ap->stats.unhandled_irq = 1;
ap->stats.idle_irq = 1; ap->stats.idle_irq = 1;
...@@ -3041,6 +2885,10 @@ int ata_device_add(struct ata_probe_ent *ent) ...@@ -3041,6 +2885,10 @@ int ata_device_add(struct ata_probe_ent *ent)
return 0; return 0;
} }
/* TODO: ack irq here, to ensure it won't scream
* when we enable it?
*/
/* obtain irq, that is shared between channels */ /* obtain irq, that is shared between channels */
if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
DRV_NAME, host_set)) DRV_NAME, host_set))
...@@ -3055,12 +2903,17 @@ int ata_device_add(struct ata_probe_ent *ent) ...@@ -3055,12 +2903,17 @@ int ata_device_add(struct ata_probe_ent *ent)
ap = host_set->ports[i]; ap = host_set->ports[i];
DPRINTK("ata%u: probe begin\n", ap->id); DPRINTK("ata%u: probe begin\n", ap->id);
queue_work(ata_wq, &ap->probe_task); /* start probe */ rc = ata_bus_probe(ap);
DPRINTK("ata%u: probe end\n", ap->id);
DPRINTK("ata%u: probe-wait begin\n", ap->id); if (rc) {
down(&ap->probe_sem); /* wait for end */ /* FIXME: do something useful here?
* Current libata behavior will
DPRINTK("ata%u: probe-wait end\n", ap->id); * tear down everything when
* the module is removed
* or the h/w is unplugged.
*/
}
rc = scsi_add_host(ap->host, &pdev->dev); rc = scsi_add_host(ap->host, &pdev->dev);
if (rc) { if (rc) {
...@@ -3480,7 +3333,7 @@ EXPORT_SYMBOL_GPL(ata_exec_command_mmio); ...@@ -3480,7 +3333,7 @@ EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_port_stop);
EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_fill_sg); EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio); EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio); EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
......
...@@ -81,7 +81,7 @@ static void pdc_eng_timeout(struct ata_port *ap); ...@@ -81,7 +81,7 @@ static void pdc_eng_timeout(struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap);
static void pdc_phy_reset(struct ata_port *ap); static void pdc_phy_reset(struct ata_port *ap);
static void pdc_fill_sg(struct ata_queued_cmd *qc); static void pdc_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static inline void pdc_dma_complete (struct ata_port *ap, static inline void pdc_dma_complete (struct ata_port *ap,
...@@ -114,7 +114,7 @@ static struct ata_port_operations pdc_sata_ops = { ...@@ -114,7 +114,7 @@ static struct ata_port_operations pdc_sata_ops = {
.phy_reset = pdc_phy_reset, .phy_reset = pdc_phy_reset,
.bmdma_setup = pdc_dma_setup, .bmdma_setup = pdc_dma_setup,
.bmdma_start = pdc_dma_start, .bmdma_start = pdc_dma_start,
.fill_sg = pdc_fill_sg, .qc_prep = pdc_qc_prep,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt, .irq_handler = pdc_interrupt,
.scr_read = pdc_sata_scr_read, .scr_read = pdc_sata_scr_read,
...@@ -261,14 +261,14 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, ...@@ -261,14 +261,14 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
} }
static void pdc_fill_sg(struct ata_queued_cmd *qc) static void pdc_qc_prep(struct ata_queued_cmd *qc)
{ {
struct pdc_port_priv *pp = qc->ap->private_data; struct pdc_port_priv *pp = qc->ap->private_data;
unsigned int i; unsigned int i;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
ata_fill_sg(qc); ata_qc_prep(qc);
i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt); i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt);
......
...@@ -131,7 +131,7 @@ static struct ata_port_operations sil_ops = { ...@@ -131,7 +131,7 @@ static struct ata_port_operations sil_ops = {
.post_set_mode = sil_post_set_mode, .post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup_mmio, .bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio, .bmdma_start = ata_bmdma_start_mmio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.scr_read = sil_scr_read, .scr_read = sil_scr_read,
......
...@@ -100,7 +100,7 @@ static struct ata_port_operations sis_ops = { ...@@ -100,7 +100,7 @@ static struct ata_port_operations sis_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio, .bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio, .bmdma_start = ata_bmdma_start_pio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.scr_read = sis_scr_read, .scr_read = sis_scr_read,
......
...@@ -233,7 +233,7 @@ static struct ata_port_operations k2_sata_ops = { ...@@ -233,7 +233,7 @@ static struct ata_port_operations k2_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_mmio, .bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio, .bmdma_start = ata_bmdma_start_mmio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.scr_read = k2_sata_scr_read, .scr_read = k2_sata_scr_read,
......
...@@ -153,7 +153,7 @@ static void pdc_eng_timeout(struct ata_port *ap); ...@@ -153,7 +153,7 @@ static void pdc_eng_timeout(struct ata_port *ap);
static void pdc_20621_phy_reset (struct ata_port *ap); static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap);
static void pdc20621_fill_sg(struct ata_queued_cmd *qc); static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set); static void pdc20621_host_stop(struct ata_host_set *host_set);
...@@ -200,7 +200,7 @@ static struct ata_port_operations pdc_20621_ops = { ...@@ -200,7 +200,7 @@ static struct ata_port_operations pdc_20621_ops = {
.phy_reset = pdc_20621_phy_reset, .phy_reset = pdc_20621_phy_reset,
.bmdma_setup = pdc20621_dma_setup, .bmdma_setup = pdc20621_dma_setup,
.bmdma_start = pdc20621_dma_start, .bmdma_start = pdc20621_dma_start,
.fill_sg = pdc20621_fill_sg, .qc_prep = pdc20621_qc_prep,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc20621_interrupt, .irq_handler = pdc20621_interrupt,
.port_start = pdc_port_start, .port_start = pdc_port_start,
...@@ -434,7 +434,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, ...@@ -434,7 +434,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
buf32[dw + 3]); buf32[dw + 3]);
} }
static void pdc20621_fill_sg(struct ata_queued_cmd *qc) static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
{ {
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
...@@ -446,6 +446,9 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -446,6 +446,9 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
unsigned int i, last, idx, total_len = 0, sgt_len; unsigned int i, last, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
if (!(qc->flags & ATA_QCFLAG_SG))
return;
VPRINTK("ata%u: ENTER\n", ap->id); VPRINTK("ata%u: ENTER\n", ap->id);
/* hard-code chip #0 */ /* hard-code chip #0 */
......
...@@ -108,7 +108,7 @@ static struct ata_port_operations svia_sata_ops = { ...@@ -108,7 +108,7 @@ static struct ata_port_operations svia_sata_ops = {
.bmdma_setup = ata_bmdma_setup_pio, .bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio, .bmdma_start = ata_bmdma_start_pio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
......
...@@ -215,7 +215,7 @@ static struct ata_port_operations vsc_sata_ops = { ...@@ -215,7 +215,7 @@ static struct ata_port_operations vsc_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_mmio, .bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio, .bmdma_start = ata_bmdma_start_mmio,
.fill_sg = ata_fill_sg, .qc_prep = ata_qc_prep,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = vsc_sata_interrupt, .irq_handler = vsc_sata_interrupt,
.scr_read = vsc_sata_scr_read, .scr_read = vsc_sata_scr_read,
......
...@@ -133,15 +133,6 @@ enum { ...@@ -133,15 +133,6 @@ enum {
BUS_IDENTIFY = 8, BUS_IDENTIFY = 8,
BUS_PACKET = 9, BUS_PACKET = 9,
/* thread states */
THR_UNKNOWN = 0,
THR_PORT_RESET = (THR_UNKNOWN + 1),
THR_AWAIT_DEATH = (THR_PORT_RESET + 1),
THR_PROBE_FAILED = (THR_AWAIT_DEATH + 1),
THR_IDLE = (THR_PROBE_FAILED + 1),
THR_PROBE_SUCCESS = (THR_IDLE + 1),
THR_PROBE_START = (THR_PROBE_SUCCESS + 1),
/* SATA port states */ /* SATA port states */
PORT_UNKNOWN = 0, PORT_UNKNOWN = 0,
PORT_ENABLED = 1, PORT_ENABLED = 1,
...@@ -294,18 +285,12 @@ struct ata_port { ...@@ -294,18 +285,12 @@ struct ata_port {
struct ata_host_stats stats; struct ata_host_stats stats;
struct ata_host_set *host_set; struct ata_host_set *host_set;
struct semaphore probe_sem;
unsigned int thr_state;
struct work_struct packet_task; struct work_struct packet_task;
struct work_struct pio_task; struct work_struct pio_task;
unsigned int pio_task_state; unsigned int pio_task_state;
unsigned long pio_task_timeout; unsigned long pio_task_timeout;
struct work_struct probe_task;
void *private_data; void *private_data;
}; };
...@@ -330,7 +315,7 @@ struct ata_port_operations { ...@@ -330,7 +315,7 @@ struct ata_port_operations {
void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc);
void (*fill_sg) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc);
void (*eng_timeout) (struct ata_port *ap); void (*eng_timeout) (struct ata_port *ap);
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
...@@ -390,7 +375,7 @@ extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); ...@@ -390,7 +375,7 @@ extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap); extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_fill_sg(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s, extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
...@@ -556,4 +541,44 @@ static inline unsigned int sata_dev_present(struct ata_port *ap) ...@@ -556,4 +541,44 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
} }
static inline void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
}
static inline void ata_bmdma_ack_irq(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
writeb(readb(mmio), mmio);
} else {
unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
outb(inb(addr), addr);
}
}
static inline u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
#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