diff options
Diffstat (limited to 'drivers/scsi/sata_sil24.c')
-rw-r--r-- | drivers/scsi/sata_sil24.c | 102 |
1 files changed, 53 insertions, 49 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 923130185a9e..9a53a5ed38c5 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -249,9 +249,9 @@ static u8 sil24_check_status(struct ata_port *ap); | |||
249 | static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); | 249 | static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); |
250 | static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); | 250 | static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); |
251 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | 251 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); |
252 | static void sil24_phy_reset(struct ata_port *ap); | 252 | static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes); |
253 | static void sil24_qc_prep(struct ata_queued_cmd *qc); | 253 | static void sil24_qc_prep(struct ata_queued_cmd *qc); |
254 | static int sil24_qc_issue(struct ata_queued_cmd *qc); | 254 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
255 | static void sil24_irq_clear(struct ata_port *ap); | 255 | static void sil24_irq_clear(struct ata_port *ap); |
256 | static void sil24_eng_timeout(struct ata_port *ap); | 256 | static void sil24_eng_timeout(struct ata_port *ap); |
257 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); | 257 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); |
@@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
262 | 262 | ||
263 | static const struct pci_device_id sil24_pci_tbl[] = { | 263 | static const struct pci_device_id sil24_pci_tbl[] = { |
264 | { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, | 264 | { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, |
265 | { 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, | ||
265 | { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 }, | 266 | { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 }, |
266 | { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, | 267 | { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, |
267 | { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, | 268 | { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, |
@@ -280,11 +281,11 @@ static struct scsi_host_template sil24_sht = { | |||
280 | .name = DRV_NAME, | 281 | .name = DRV_NAME, |
281 | .ioctl = ata_scsi_ioctl, | 282 | .ioctl = ata_scsi_ioctl, |
282 | .queuecommand = ata_scsi_queuecmd, | 283 | .queuecommand = ata_scsi_queuecmd, |
284 | .eh_timed_out = ata_scsi_timed_out, | ||
283 | .eh_strategy_handler = ata_scsi_error, | 285 | .eh_strategy_handler = ata_scsi_error, |
284 | .can_queue = ATA_DEF_QUEUE, | 286 | .can_queue = ATA_DEF_QUEUE, |
285 | .this_id = ATA_SHT_THIS_ID, | 287 | .this_id = ATA_SHT_THIS_ID, |
286 | .sg_tablesize = LIBATA_MAX_PRD, | 288 | .sg_tablesize = LIBATA_MAX_PRD, |
287 | .max_sectors = ATA_MAX_SECTORS, | ||
288 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 289 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
289 | .emulated = ATA_SHT_EMULATED, | 290 | .emulated = ATA_SHT_EMULATED, |
290 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 291 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -305,7 +306,7 @@ static const struct ata_port_operations sil24_ops = { | |||
305 | 306 | ||
306 | .tf_read = sil24_tf_read, | 307 | .tf_read = sil24_tf_read, |
307 | 308 | ||
308 | .phy_reset = sil24_phy_reset, | 309 | .probe_reset = sil24_probe_reset, |
309 | 310 | ||
310 | .qc_prep = sil24_qc_prep, | 311 | .qc_prep = sil24_qc_prep, |
311 | .qc_issue = sil24_qc_issue, | 312 | .qc_issue = sil24_qc_issue, |
@@ -335,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = { | |||
335 | { | 336 | { |
336 | .sht = &sil24_sht, | 337 | .sht = &sil24_sht, |
337 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 338 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
338 | ATA_FLAG_SRST | ATA_FLAG_MMIO | | 339 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
339 | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4), | 340 | SIL24_NPORTS2FLAG(4), |
340 | .pio_mask = 0x1f, /* pio0-4 */ | 341 | .pio_mask = 0x1f, /* pio0-4 */ |
341 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 342 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
342 | .udma_mask = 0x3f, /* udma0-5 */ | 343 | .udma_mask = 0x3f, /* udma0-5 */ |
@@ -346,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = { | |||
346 | { | 347 | { |
347 | .sht = &sil24_sht, | 348 | .sht = &sil24_sht, |
348 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 349 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
349 | ATA_FLAG_SRST | ATA_FLAG_MMIO | | 350 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
350 | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2), | 351 | SIL24_NPORTS2FLAG(2), |
351 | .pio_mask = 0x1f, /* pio0-4 */ | 352 | .pio_mask = 0x1f, /* pio0-4 */ |
352 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 353 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
353 | .udma_mask = 0x3f, /* udma0-5 */ | 354 | .udma_mask = 0x3f, /* udma0-5 */ |
@@ -357,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = { | |||
357 | { | 358 | { |
358 | .sht = &sil24_sht, | 359 | .sht = &sil24_sht, |
359 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 360 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
360 | ATA_FLAG_SRST | ATA_FLAG_MMIO | | 361 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
361 | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1), | 362 | SIL24_NPORTS2FLAG(1), |
362 | .pio_mask = 0x1f, /* pio0-4 */ | 363 | .pio_mask = 0x1f, /* pio0-4 */ |
363 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 364 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
364 | .udma_mask = 0x3f, /* udma0-5 */ | 365 | .udma_mask = 0x3f, /* udma0-5 */ |
@@ -370,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) | |||
370 | { | 371 | { |
371 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 372 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
372 | 373 | ||
373 | if (ap->cdb_len == 16) | 374 | if (dev->cdb_len == 16) |
374 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); | 375 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); |
375 | else | 376 | else |
376 | writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); | 377 | writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); |
@@ -427,14 +428,23 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |||
427 | *tf = pp->tf; | 428 | *tf = pp->tf; |
428 | } | 429 | } |
429 | 430 | ||
430 | static int sil24_issue_SRST(struct ata_port *ap) | 431 | static int sil24_softreset(struct ata_port *ap, int verbose, |
432 | unsigned int *class) | ||
431 | { | 433 | { |
432 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 434 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
433 | struct sil24_port_priv *pp = ap->private_data; | 435 | struct sil24_port_priv *pp = ap->private_data; |
434 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; | 436 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; |
435 | dma_addr_t paddr = pp->cmd_block_dma; | 437 | dma_addr_t paddr = pp->cmd_block_dma; |
438 | unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ; | ||
436 | u32 irq_enable, irq_stat; | 439 | u32 irq_enable, irq_stat; |
437 | int cnt; | 440 | |
441 | DPRINTK("ENTER\n"); | ||
442 | |||
443 | if (!sata_dev_present(ap)) { | ||
444 | DPRINTK("PHY reports no device\n"); | ||
445 | *class = ATA_DEV_NONE; | ||
446 | goto out; | ||
447 | } | ||
438 | 448 | ||
439 | /* temporarily turn off IRQs during SRST */ | 449 | /* temporarily turn off IRQs during SRST */ |
440 | irq_enable = readl(port + PORT_IRQ_ENABLE_SET); | 450 | irq_enable = readl(port + PORT_IRQ_ENABLE_SET); |
@@ -451,7 +461,7 @@ static int sil24_issue_SRST(struct ata_port *ap) | |||
451 | 461 | ||
452 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); | 462 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); |
453 | 463 | ||
454 | for (cnt = 0; cnt < 100; cnt++) { | 464 | do { |
455 | irq_stat = readl(port + PORT_IRQ_STAT); | 465 | irq_stat = readl(port + PORT_IRQ_STAT); |
456 | writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ | 466 | writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ |
457 | 467 | ||
@@ -459,36 +469,42 @@ static int sil24_issue_SRST(struct ata_port *ap) | |||
459 | if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) | 469 | if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) |
460 | break; | 470 | break; |
461 | 471 | ||
462 | msleep(1); | 472 | msleep(100); |
463 | } | 473 | } while (time_before(jiffies, timeout)); |
464 | 474 | ||
465 | /* restore IRQs */ | 475 | /* restore IRQs */ |
466 | writel(irq_enable, port + PORT_IRQ_ENABLE_SET); | 476 | writel(irq_enable, port + PORT_IRQ_ENABLE_SET); |
467 | 477 | ||
468 | if (!(irq_stat & PORT_IRQ_COMPLETE)) | 478 | if (!(irq_stat & PORT_IRQ_COMPLETE)) { |
469 | return -1; | 479 | DPRINTK("EXIT, srst failed\n"); |
480 | return -EIO; | ||
481 | } | ||
470 | 482 | ||
471 | /* update TF */ | ||
472 | sil24_update_tf(ap); | 483 | sil24_update_tf(ap); |
484 | *class = ata_dev_classify(&pp->tf); | ||
485 | |||
486 | if (*class == ATA_DEV_UNKNOWN) | ||
487 | *class = ATA_DEV_NONE; | ||
488 | |||
489 | out: | ||
490 | DPRINTK("EXIT, class=%u\n", *class); | ||
473 | return 0; | 491 | return 0; |
474 | } | 492 | } |
475 | 493 | ||
476 | static void sil24_phy_reset(struct ata_port *ap) | 494 | static int sil24_hardreset(struct ata_port *ap, int verbose, |
495 | unsigned int *class) | ||
477 | { | 496 | { |
478 | struct sil24_port_priv *pp = ap->private_data; | 497 | unsigned int dummy_class; |
479 | 498 | ||
480 | __sata_phy_reset(ap); | 499 | /* sil24 doesn't report device signature after hard reset */ |
481 | if (ap->flags & ATA_FLAG_PORT_DISABLED) | 500 | return sata_std_hardreset(ap, verbose, &dummy_class); |
482 | return; | 501 | } |
483 | |||
484 | if (sil24_issue_SRST(ap) < 0) { | ||
485 | printk(KERN_ERR DRV_NAME | ||
486 | " ata%u: SRST failed, disabling port\n", ap->id); | ||
487 | ap->ops->port_disable(ap); | ||
488 | return; | ||
489 | } | ||
490 | 502 | ||
491 | ap->device->class = ata_dev_classify(&pp->tf); | 503 | static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) |
504 | { | ||
505 | return ata_drive_probe_reset(ap, ata_std_probeinit, | ||
506 | sil24_softreset, sil24_hardreset, | ||
507 | ata_std_postreset, classes); | ||
492 | } | 508 | } |
493 | 509 | ||
494 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, | 510 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, |
@@ -533,7 +549,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
533 | prb = &cb->atapi.prb; | 549 | prb = &cb->atapi.prb; |
534 | sge = cb->atapi.sge; | 550 | sge = cb->atapi.sge; |
535 | memset(cb->atapi.cdb, 0, 32); | 551 | memset(cb->atapi.cdb, 0, 32); |
536 | memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); | 552 | memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); |
537 | 553 | ||
538 | if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { | 554 | if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { |
539 | if (qc->tf.flags & ATA_TFLAG_WRITE) | 555 | if (qc->tf.flags & ATA_TFLAG_WRITE) |
@@ -557,7 +573,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
557 | sil24_fill_sg(qc, sge); | 573 | sil24_fill_sg(qc, sge); |
558 | } | 574 | } |
559 | 575 | ||
560 | static int sil24_qc_issue(struct ata_queued_cmd *qc) | 576 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) |
561 | { | 577 | { |
562 | struct ata_port *ap = qc->ap; | 578 | struct ata_port *ap = qc->ap; |
563 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 579 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
@@ -638,23 +654,10 @@ static void sil24_eng_timeout(struct ata_port *ap) | |||
638 | struct ata_queued_cmd *qc; | 654 | struct ata_queued_cmd *qc; |
639 | 655 | ||
640 | qc = ata_qc_from_tag(ap, ap->active_tag); | 656 | qc = ata_qc_from_tag(ap, ap->active_tag); |
641 | if (!qc) { | ||
642 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", | ||
643 | ap->id); | ||
644 | return; | ||
645 | } | ||
646 | 657 | ||
647 | /* | ||
648 | * hack alert! We cannot use the supplied completion | ||
649 | * function from inside the ->eh_strategy_handler() thread. | ||
650 | * libata is the only user of ->eh_strategy_handler() in | ||
651 | * any kernel, so the default scsi_done() assumes it is | ||
652 | * not being called from the SCSI EH. | ||
653 | */ | ||
654 | printk(KERN_ERR "ata%u: command timeout\n", ap->id); | 658 | printk(KERN_ERR "ata%u: command timeout\n", ap->id); |
655 | qc->scsidone = scsi_finish_command; | 659 | qc->err_mask |= AC_ERR_TIMEOUT; |
656 | qc->err_mask |= AC_ERR_OTHER; | 660 | ata_eh_qc_complete(qc); |
657 | ata_qc_complete(qc); | ||
658 | 661 | ||
659 | sil24_reset_controller(ap); | 662 | sil24_reset_controller(ap); |
660 | } | 663 | } |
@@ -895,6 +898,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
895 | probe_ent->sht = pinfo->sht; | 898 | probe_ent->sht = pinfo->sht; |
896 | probe_ent->host_flags = pinfo->host_flags; | 899 | probe_ent->host_flags = pinfo->host_flags; |
897 | probe_ent->pio_mask = pinfo->pio_mask; | 900 | probe_ent->pio_mask = pinfo->pio_mask; |
901 | probe_ent->mwdma_mask = pinfo->mwdma_mask; | ||
898 | probe_ent->udma_mask = pinfo->udma_mask; | 902 | probe_ent->udma_mask = pinfo->udma_mask; |
899 | probe_ent->port_ops = pinfo->port_ops; | 903 | probe_ent->port_ops = pinfo->port_ops; |
900 | probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags); | 904 | probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags); |