Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sonic Zhang and committed by
Jeff Garzik
65c0d4e5 7368f919

+120 -4
+120 -4
drivers/ata/pata_bf54x.c
··· 1272 1272 1273 1273 void bfin_thaw(struct ata_port *ap) 1274 1274 { 1275 + dev_dbg(ap->dev, "in atapi dma thaw\n"); 1275 1276 bfin_check_status(ap); 1276 - bfin_irq_clear(ap); 1277 1277 bfin_irq_on(ap); 1278 1278 } 1279 1279 ··· 1339 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 1459 static struct scsi_host_template bfin_sht = { 1343 1460 ATA_BASE_SHT(DRV_NAME), 1344 1461 .sg_tablesize = SG_NONE, 1345 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 1466 .inherits = &ata_sff_port_ops, 1350 1467 1351 1468 .set_piomode = bfin_set_piomode, ··· 1487 1370 .thaw = bfin_thaw, 1488 1371 .softreset = bfin_softreset, 1489 1372 .postreset = bfin_postreset, 1490 - .post_internal_cmd = bfin_bmdma_stop, 1491 1373 1492 1374 .sff_irq_clear = bfin_irq_clear, 1493 1375 .sff_irq_on = bfin_irq_on, ··· 1623 1507 } 1624 1508 1625 1509 if (ata_host_activate(host, platform_get_irq(pdev, 0), 1626 - ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) { 1510 + bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) { 1627 1511 peripheral_free_list(atapi_io_port); 1628 1512 dev_err(&pdev->dev, "Fail to attach ATAPI device\n"); 1629 1513 return -ENODEV;