diff options
| -rw-r--r-- | drivers/ata/pata_bf54x.c | 124 |
1 files changed, 120 insertions, 4 deletions
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index a75de0684c15..9ab89732cf94 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c | |||
| @@ -1272,8 +1272,8 @@ static void bfin_freeze(struct ata_port *ap) | |||
| 1272 | 1272 | ||
| 1273 | void bfin_thaw(struct ata_port *ap) | 1273 | void bfin_thaw(struct ata_port *ap) |
| 1274 | { | 1274 | { |
| 1275 | dev_dbg(ap->dev, "in atapi dma thaw\n"); | ||
| 1275 | bfin_check_status(ap); | 1276 | bfin_check_status(ap); |
| 1276 | bfin_irq_clear(ap); | ||
| 1277 | bfin_irq_on(ap); | 1277 | bfin_irq_on(ap); |
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| @@ -1339,13 +1339,130 @@ static int bfin_port_start(struct ata_port *ap) | |||
| 1339 | return 0; | 1339 | return 0; |
| 1340 | } | 1340 | } |
| 1341 | 1341 | ||
| 1342 | static unsigned int bfin_ata_host_intr(struct ata_port *ap, | ||
| 1343 | struct ata_queued_cmd *qc) | ||
| 1344 | { | ||
| 1345 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
| 1346 | u8 status, host_stat = 0; | ||
| 1347 | |||
| 1348 | VPRINTK("ata%u: protocol %d task_state %d\n", | ||
| 1349 | ap->print_id, qc->tf.protocol, ap->hsm_task_state); | ||
| 1350 | |||
| 1351 | /* Check whether we are expecting interrupt in this state */ | ||
| 1352 | switch (ap->hsm_task_state) { | ||
| 1353 | case HSM_ST_FIRST: | ||
| 1354 | /* Some pre-ATAPI-4 devices assert INTRQ | ||
| 1355 | * at this state when ready to receive CDB. | ||
| 1356 | */ | ||
| 1357 | |||
| 1358 | /* Check the ATA_DFLAG_CDB_INTR flag is enough here. | ||
| 1359 | * The flag was turned on only for atapi devices. | ||
| 1360 | * No need to check is_atapi_taskfile(&qc->tf) again. | ||
| 1361 | */ | ||
| 1362 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | ||
| 1363 | goto idle_irq; | ||
| 1364 | break; | ||
| 1365 | case HSM_ST_LAST: | ||
| 1366 | if (qc->tf.protocol == ATA_PROT_DMA || | ||
| 1367 | qc->tf.protocol == ATAPI_PROT_DMA) { | ||
| 1368 | /* check status of DMA engine */ | ||
| 1369 | host_stat = ap->ops->bmdma_status(ap); | ||
| 1370 | VPRINTK("ata%u: host_stat 0x%X\n", | ||
| 1371 | ap->print_id, host_stat); | ||
| 1372 | |||
| 1373 | /* if it's not our irq... */ | ||
| 1374 | if (!(host_stat & ATA_DMA_INTR)) | ||
| 1375 | goto idle_irq; | ||
| 1376 | |||
| 1377 | /* before we do anything else, clear DMA-Start bit */ | ||
| 1378 | ap->ops->bmdma_stop(qc); | ||
| 1379 | |||
| 1380 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
| 1381 | /* error when transfering data to/from memory */ | ||
| 1382 | qc->err_mask |= AC_ERR_HOST_BUS; | ||
| 1383 | ap->hsm_task_state = HSM_ST_ERR; | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | break; | ||
| 1387 | case HSM_ST: | ||
| 1388 | break; | ||
| 1389 | default: | ||
| 1390 | goto idle_irq; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | /* check altstatus */ | ||
| 1394 | status = ap->ops->sff_check_altstatus(ap); | ||
| 1395 | if (status & ATA_BUSY) | ||
| 1396 | goto busy_ata; | ||
| 1397 | |||
| 1398 | /* check main status, clearing INTRQ */ | ||
| 1399 | status = ap->ops->sff_check_status(ap); | ||
| 1400 | if (unlikely(status & ATA_BUSY)) | ||
| 1401 | goto busy_ata; | ||
| 1402 | |||
| 1403 | /* ack bmdma irq events */ | ||
| 1404 | ap->ops->sff_irq_clear(ap); | ||
| 1405 | |||
| 1406 | ata_sff_hsm_move(ap, qc, status, 0); | ||
| 1407 | |||
| 1408 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | ||
| 1409 | qc->tf.protocol == ATAPI_PROT_DMA)) | ||
| 1410 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
| 1411 | |||
| 1412 | busy_ata: | ||
| 1413 | return 1; /* irq handled */ | ||
| 1414 | |||
| 1415 | idle_irq: | ||
| 1416 | ap->stats.idle_irq++; | ||
| 1417 | |||
| 1418 | #ifdef ATA_IRQ_TRAP | ||
| 1419 | if ((ap->stats.idle_irq % 1000) == 0) { | ||
| 1420 | ap->ops->irq_ack(ap, 0); /* debug trap */ | ||
| 1421 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | ||
| 1422 | return 1; | ||
| 1423 | } | ||
| 1424 | #endif | ||
| 1425 | return 0; /* irq not handled */ | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance) | ||
| 1429 | { | ||
| 1430 | struct ata_host *host = dev_instance; | ||
| 1431 | unsigned int i; | ||
| 1432 | unsigned int handled = 0; | ||
| 1433 | unsigned long flags; | ||
| 1434 | |||
| 1435 | /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ | ||
| 1436 | spin_lock_irqsave(&host->lock, flags); | ||
| 1437 | |||
| 1438 | for (i = 0; i < host->n_ports; i++) { | ||
| 1439 | struct ata_port *ap; | ||
| 1440 | |||
| 1441 | ap = host->ports[i]; | ||
| 1442 | if (ap && | ||
| 1443 | !(ap->flags & ATA_FLAG_DISABLED)) { | ||
| 1444 | struct ata_queued_cmd *qc; | ||
| 1445 | |||
| 1446 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | ||
| 1447 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && | ||
| 1448 | (qc->flags & ATA_QCFLAG_ACTIVE)) | ||
| 1449 | handled |= bfin_ata_host_intr(ap, qc); | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1454 | |||
| 1455 | return IRQ_RETVAL(handled); | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | |||
| 1342 | static struct scsi_host_template bfin_sht = { | 1459 | static struct scsi_host_template bfin_sht = { |
| 1343 | ATA_BASE_SHT(DRV_NAME), | 1460 | ATA_BASE_SHT(DRV_NAME), |
| 1344 | .sg_tablesize = SG_NONE, | 1461 | .sg_tablesize = SG_NONE, |
| 1345 | .dma_boundary = ATA_DMA_BOUNDARY, | 1462 | .dma_boundary = ATA_DMA_BOUNDARY, |
| 1346 | }; | 1463 | }; |
| 1347 | 1464 | ||
| 1348 | static const struct ata_port_operations bfin_pata_ops = { | 1465 | static struct ata_port_operations bfin_pata_ops = { |
| 1349 | .inherits = &ata_sff_port_ops, | 1466 | .inherits = &ata_sff_port_ops, |
| 1350 | 1467 | ||
| 1351 | .set_piomode = bfin_set_piomode, | 1468 | .set_piomode = bfin_set_piomode, |
| @@ -1370,7 +1487,6 @@ static const struct ata_port_operations bfin_pata_ops = { | |||
| 1370 | .thaw = bfin_thaw, | 1487 | .thaw = bfin_thaw, |
| 1371 | .softreset = bfin_softreset, | 1488 | .softreset = bfin_softreset, |
| 1372 | .postreset = bfin_postreset, | 1489 | .postreset = bfin_postreset, |
| 1373 | .post_internal_cmd = bfin_bmdma_stop, | ||
| 1374 | 1490 | ||
| 1375 | .sff_irq_clear = bfin_irq_clear, | 1491 | .sff_irq_clear = bfin_irq_clear, |
| 1376 | .sff_irq_on = bfin_irq_on, | 1492 | .sff_irq_on = bfin_irq_on, |
| @@ -1507,7 +1623,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) | |||
| 1507 | } | 1623 | } |
| 1508 | 1624 | ||
| 1509 | if (ata_host_activate(host, platform_get_irq(pdev, 0), | 1625 | if (ata_host_activate(host, platform_get_irq(pdev, 0), |
| 1510 | ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) { | 1626 | bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) { |
| 1511 | peripheral_free_list(atapi_io_port); | 1627 | peripheral_free_list(atapi_io_port); |
| 1512 | dev_err(&pdev->dev, "Fail to attach ATAPI device\n"); | 1628 | dev_err(&pdev->dev, "Fail to attach ATAPI device\n"); |
| 1513 | return -ENODEV; | 1629 | return -ENODEV; |
