aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_bf54x.c
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2008-04-25 05:19:25 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-29 02:17:18 -0400
commit65c0d4e54ae4b81d8c8bb685169e48306656bb5c (patch)
treec1e7eb0b88c16cc17c9a33431246e0114af6ccd7 /drivers/ata/pata_bf54x.c
parent7368f91926a2870a8c3f9546d86535ce71ae0757 (diff)
Fix bug - Implement bfin ata interrupt handler to avoid "irq 68 nobody cared" (v2)
Return IRQ_HANDLED when bfin ata device is busy. http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3513 v1-v2: - fold api breakage fixing patch together. - mark 'static', not 'inline'. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_bf54x.c')
-rw-r--r--drivers/ata/pata_bf54x.c124
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
1273void bfin_thaw(struct ata_port *ap) 1273void 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
1342static 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
1412busy_ata:
1413 return 1; /* irq handled */
1414
1415idle_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
1428static 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
1342static struct scsi_host_template bfin_sht = { 1459static 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
1348static const struct ata_port_operations bfin_pata_ops = { 1465static 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;