diff options
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r-- | drivers/ata/sata_sil24.c | 247 |
1 files changed, 92 insertions, 155 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index df7988df7908..27a110110077 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -254,7 +254,6 @@ enum { | |||
254 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | 254 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
255 | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | | 255 | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | |
256 | ATA_FLAG_AN | ATA_FLAG_PMP, | 256 | ATA_FLAG_AN | ATA_FLAG_PMP, |
257 | SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, | ||
258 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ | 257 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ |
259 | 258 | ||
260 | IRQ_STAT_4PORTS = 0xf, | 259 | IRQ_STAT_4PORTS = 0xf, |
@@ -286,45 +285,45 @@ static struct sil24_cerr_info { | |||
286 | "device error via D2H FIS" }, | 285 | "device error via D2H FIS" }, |
287 | [PORT_CERR_SDB] = { AC_ERR_DEV, 0, | 286 | [PORT_CERR_SDB] = { AC_ERR_DEV, 0, |
288 | "device error via SDB FIS" }, | 287 | "device error via SDB FIS" }, |
289 | [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, | 288 | [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_RESET, |
290 | "error in data FIS" }, | 289 | "error in data FIS" }, |
291 | [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, | 290 | [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_RESET, |
292 | "failed to transmit command FIS" }, | 291 | "failed to transmit command FIS" }, |
293 | [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 292 | [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET, |
294 | "protocol mismatch" }, | 293 | "protocol mismatch" }, |
295 | [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 294 | [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_RESET, |
296 | "data directon mismatch" }, | 295 | "data directon mismatch" }, |
297 | [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 296 | [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_RESET, |
298 | "ran out of SGEs while writing" }, | 297 | "ran out of SGEs while writing" }, |
299 | [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 298 | [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_RESET, |
300 | "ran out of SGEs while reading" }, | 299 | "ran out of SGEs while reading" }, |
301 | [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 300 | [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_RESET, |
302 | "invalid data directon for ATAPI CDB" }, | 301 | "invalid data directon for ATAPI CDB" }, |
303 | [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, | 302 | [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET, |
304 | "SGT not on qword boundary" }, | 303 | "SGT not on qword boundary" }, |
305 | [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 304 | [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
306 | "PCI target abort while fetching SGT" }, | 305 | "PCI target abort while fetching SGT" }, |
307 | [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 306 | [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
308 | "PCI master abort while fetching SGT" }, | 307 | "PCI master abort while fetching SGT" }, |
309 | [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 308 | [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
310 | "PCI parity error while fetching SGT" }, | 309 | "PCI parity error while fetching SGT" }, |
311 | [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, | 310 | [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET, |
312 | "PRB not on qword boundary" }, | 311 | "PRB not on qword boundary" }, |
313 | [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 312 | [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
314 | "PCI target abort while fetching PRB" }, | 313 | "PCI target abort while fetching PRB" }, |
315 | [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 314 | [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
316 | "PCI master abort while fetching PRB" }, | 315 | "PCI master abort while fetching PRB" }, |
317 | [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 316 | [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
318 | "PCI parity error while fetching PRB" }, | 317 | "PCI parity error while fetching PRB" }, |
319 | [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 318 | [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
320 | "undefined error while transferring data" }, | 319 | "undefined error while transferring data" }, |
321 | [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 320 | [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
322 | "PCI target abort while transferring data" }, | 321 | "PCI target abort while transferring data" }, |
323 | [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 322 | [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
324 | "PCI master abort while transferring data" }, | 323 | "PCI master abort while transferring data" }, |
325 | [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, | 324 | [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET, |
326 | "PCI parity error while transferring data" }, | 325 | "PCI parity error while transferring data" }, |
327 | [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET, | 326 | [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_RESET, |
328 | "FIS received while sending service FIS" }, | 327 | "FIS received while sending service FIS" }, |
329 | }; | 328 | }; |
330 | 329 | ||
@@ -337,23 +336,26 @@ static struct sil24_cerr_info { | |||
337 | struct sil24_port_priv { | 336 | struct sil24_port_priv { |
338 | union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ | 337 | union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ |
339 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ | 338 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ |
340 | struct ata_taskfile tf; /* Cached taskfile registers */ | ||
341 | int do_port_rst; | 339 | int do_port_rst; |
342 | }; | 340 | }; |
343 | 341 | ||
344 | static void sil24_dev_config(struct ata_device *dev); | 342 | static void sil24_dev_config(struct ata_device *dev); |
345 | static u8 sil24_check_status(struct ata_port *ap); | ||
346 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); | 343 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); |
347 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); | 344 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); |
348 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | ||
349 | static int sil24_qc_defer(struct ata_queued_cmd *qc); | 345 | static int sil24_qc_defer(struct ata_queued_cmd *qc); |
350 | static void sil24_qc_prep(struct ata_queued_cmd *qc); | 346 | static void sil24_qc_prep(struct ata_queued_cmd *qc); |
351 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); | 347 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
352 | static void sil24_irq_clear(struct ata_port *ap); | 348 | static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc); |
353 | static void sil24_pmp_attach(struct ata_port *ap); | 349 | static void sil24_pmp_attach(struct ata_port *ap); |
354 | static void sil24_pmp_detach(struct ata_port *ap); | 350 | static void sil24_pmp_detach(struct ata_port *ap); |
355 | static void sil24_freeze(struct ata_port *ap); | 351 | static void sil24_freeze(struct ata_port *ap); |
356 | static void sil24_thaw(struct ata_port *ap); | 352 | static void sil24_thaw(struct ata_port *ap); |
353 | static int sil24_softreset(struct ata_link *link, unsigned int *class, | ||
354 | unsigned long deadline); | ||
355 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, | ||
356 | unsigned long deadline); | ||
357 | static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, | ||
358 | unsigned long deadline); | ||
357 | static void sil24_error_handler(struct ata_port *ap); | 359 | static void sil24_error_handler(struct ata_port *ap); |
358 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc); | 360 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc); |
359 | static int sil24_port_start(struct ata_port *ap); | 361 | static int sil24_port_start(struct ata_port *ap); |
@@ -386,52 +388,36 @@ static struct pci_driver sil24_pci_driver = { | |||
386 | }; | 388 | }; |
387 | 389 | ||
388 | static struct scsi_host_template sil24_sht = { | 390 | static struct scsi_host_template sil24_sht = { |
389 | .module = THIS_MODULE, | 391 | ATA_NCQ_SHT(DRV_NAME), |
390 | .name = DRV_NAME, | ||
391 | .ioctl = ata_scsi_ioctl, | ||
392 | .queuecommand = ata_scsi_queuecmd, | ||
393 | .change_queue_depth = ata_scsi_change_queue_depth, | ||
394 | .can_queue = SIL24_MAX_CMDS, | 392 | .can_queue = SIL24_MAX_CMDS, |
395 | .this_id = ATA_SHT_THIS_ID, | ||
396 | .sg_tablesize = SIL24_MAX_SGE, | 393 | .sg_tablesize = SIL24_MAX_SGE, |
397 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
398 | .emulated = ATA_SHT_EMULATED, | ||
399 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
400 | .proc_name = DRV_NAME, | ||
401 | .dma_boundary = ATA_DMA_BOUNDARY, | 394 | .dma_boundary = ATA_DMA_BOUNDARY, |
402 | .slave_configure = ata_scsi_slave_config, | ||
403 | .slave_destroy = ata_scsi_slave_destroy, | ||
404 | .bios_param = ata_std_bios_param, | ||
405 | }; | 395 | }; |
406 | 396 | ||
407 | static const struct ata_port_operations sil24_ops = { | 397 | static struct ata_port_operations sil24_ops = { |
408 | .dev_config = sil24_dev_config, | 398 | .inherits = &sata_pmp_port_ops, |
409 | |||
410 | .check_status = sil24_check_status, | ||
411 | .check_altstatus = sil24_check_status, | ||
412 | .dev_select = ata_noop_dev_select, | ||
413 | |||
414 | .tf_read = sil24_tf_read, | ||
415 | 399 | ||
416 | .qc_defer = sil24_qc_defer, | 400 | .qc_defer = sil24_qc_defer, |
417 | .qc_prep = sil24_qc_prep, | 401 | .qc_prep = sil24_qc_prep, |
418 | .qc_issue = sil24_qc_issue, | 402 | .qc_issue = sil24_qc_issue, |
403 | .qc_fill_rtf = sil24_qc_fill_rtf, | ||
419 | 404 | ||
420 | .irq_clear = sil24_irq_clear, | 405 | .freeze = sil24_freeze, |
406 | .thaw = sil24_thaw, | ||
407 | .softreset = sil24_softreset, | ||
408 | .hardreset = sil24_hardreset, | ||
409 | .pmp_softreset = sil24_softreset, | ||
410 | .pmp_hardreset = sil24_pmp_hardreset, | ||
411 | .error_handler = sil24_error_handler, | ||
412 | .post_internal_cmd = sil24_post_internal_cmd, | ||
413 | .dev_config = sil24_dev_config, | ||
421 | 414 | ||
422 | .scr_read = sil24_scr_read, | 415 | .scr_read = sil24_scr_read, |
423 | .scr_write = sil24_scr_write, | 416 | .scr_write = sil24_scr_write, |
424 | |||
425 | .pmp_attach = sil24_pmp_attach, | 417 | .pmp_attach = sil24_pmp_attach, |
426 | .pmp_detach = sil24_pmp_detach, | 418 | .pmp_detach = sil24_pmp_detach, |
427 | 419 | ||
428 | .freeze = sil24_freeze, | ||
429 | .thaw = sil24_thaw, | ||
430 | .error_handler = sil24_error_handler, | ||
431 | .post_internal_cmd = sil24_post_internal_cmd, | ||
432 | |||
433 | .port_start = sil24_port_start, | 420 | .port_start = sil24_port_start, |
434 | |||
435 | #ifdef CONFIG_PM | 421 | #ifdef CONFIG_PM |
436 | .port_resume = sil24_port_resume, | 422 | .port_resume = sil24_port_resume, |
437 | #endif | 423 | #endif |
@@ -449,7 +435,6 @@ static const struct ata_port_info sil24_port_info[] = { | |||
449 | { | 435 | { |
450 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | | 436 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | |
451 | SIL24_FLAG_PCIX_IRQ_WOC, | 437 | SIL24_FLAG_PCIX_IRQ_WOC, |
452 | .link_flags = SIL24_COMMON_LFLAGS, | ||
453 | .pio_mask = 0x1f, /* pio0-4 */ | 438 | .pio_mask = 0x1f, /* pio0-4 */ |
454 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 439 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
455 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 440 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -458,7 +443,6 @@ static const struct ata_port_info sil24_port_info[] = { | |||
458 | /* sil_3132 */ | 443 | /* sil_3132 */ |
459 | { | 444 | { |
460 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), | 445 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), |
461 | .link_flags = SIL24_COMMON_LFLAGS, | ||
462 | .pio_mask = 0x1f, /* pio0-4 */ | 446 | .pio_mask = 0x1f, /* pio0-4 */ |
463 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 447 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
464 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 448 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -467,7 +451,6 @@ static const struct ata_port_info sil24_port_info[] = { | |||
467 | /* sil_3131/sil_3531 */ | 451 | /* sil_3131/sil_3531 */ |
468 | { | 452 | { |
469 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), | 453 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), |
470 | .link_flags = SIL24_COMMON_LFLAGS, | ||
471 | .pio_mask = 0x1f, /* pio0-4 */ | 454 | .pio_mask = 0x1f, /* pio0-4 */ |
472 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 455 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
473 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 456 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -482,9 +465,19 @@ static int sil24_tag(int tag) | |||
482 | return tag; | 465 | return tag; |
483 | } | 466 | } |
484 | 467 | ||
468 | static unsigned long sil24_port_offset(struct ata_port *ap) | ||
469 | { | ||
470 | return ap->port_no * PORT_REGS_SIZE; | ||
471 | } | ||
472 | |||
473 | static void __iomem *sil24_port_base(struct ata_port *ap) | ||
474 | { | ||
475 | return ap->host->iomap[SIL24_PORT_BAR] + sil24_port_offset(ap); | ||
476 | } | ||
477 | |||
485 | static void sil24_dev_config(struct ata_device *dev) | 478 | static void sil24_dev_config(struct ata_device *dev) |
486 | { | 479 | { |
487 | void __iomem *port = dev->link->ap->ioaddr.cmd_addr; | 480 | void __iomem *port = sil24_port_base(dev->link->ap); |
488 | 481 | ||
489 | if (dev->cdb_len == 16) | 482 | if (dev->cdb_len == 16) |
490 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); | 483 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); |
@@ -494,7 +487,7 @@ static void sil24_dev_config(struct ata_device *dev) | |||
494 | 487 | ||
495 | static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf) | 488 | static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf) |
496 | { | 489 | { |
497 | void __iomem *port = ap->ioaddr.cmd_addr; | 490 | void __iomem *port = sil24_port_base(ap); |
498 | struct sil24_prb __iomem *prb; | 491 | struct sil24_prb __iomem *prb; |
499 | u8 fis[6 * 4]; | 492 | u8 fis[6 * 4]; |
500 | 493 | ||
@@ -503,12 +496,6 @@ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf) | |||
503 | ata_tf_from_fis(fis, tf); | 496 | ata_tf_from_fis(fis, tf); |
504 | } | 497 | } |
505 | 498 | ||
506 | static u8 sil24_check_status(struct ata_port *ap) | ||
507 | { | ||
508 | struct sil24_port_priv *pp = ap->private_data; | ||
509 | return pp->tf.command; | ||
510 | } | ||
511 | |||
512 | static int sil24_scr_map[] = { | 499 | static int sil24_scr_map[] = { |
513 | [SCR_CONTROL] = 0, | 500 | [SCR_CONTROL] = 0, |
514 | [SCR_STATUS] = 1, | 501 | [SCR_STATUS] = 1, |
@@ -518,7 +505,7 @@ static int sil24_scr_map[] = { | |||
518 | 505 | ||
519 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) | 506 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) |
520 | { | 507 | { |
521 | void __iomem *scr_addr = ap->ioaddr.scr_addr; | 508 | void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL; |
522 | 509 | ||
523 | if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { | 510 | if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { |
524 | void __iomem *addr; | 511 | void __iomem *addr; |
@@ -531,7 +518,7 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) | |||
531 | 518 | ||
532 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) | 519 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) |
533 | { | 520 | { |
534 | void __iomem *scr_addr = ap->ioaddr.scr_addr; | 521 | void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL; |
535 | 522 | ||
536 | if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { | 523 | if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { |
537 | void __iomem *addr; | 524 | void __iomem *addr; |
@@ -542,15 +529,9 @@ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) | |||
542 | return -EINVAL; | 529 | return -EINVAL; |
543 | } | 530 | } |
544 | 531 | ||
545 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | ||
546 | { | ||
547 | struct sil24_port_priv *pp = ap->private_data; | ||
548 | *tf = pp->tf; | ||
549 | } | ||
550 | |||
551 | static void sil24_config_port(struct ata_port *ap) | 532 | static void sil24_config_port(struct ata_port *ap) |
552 | { | 533 | { |
553 | void __iomem *port = ap->ioaddr.cmd_addr; | 534 | void __iomem *port = sil24_port_base(ap); |
554 | 535 | ||
555 | /* configure IRQ WoC */ | 536 | /* configure IRQ WoC */ |
556 | if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) | 537 | if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) |
@@ -575,7 +556,7 @@ static void sil24_config_port(struct ata_port *ap) | |||
575 | 556 | ||
576 | static void sil24_config_pmp(struct ata_port *ap, int attached) | 557 | static void sil24_config_pmp(struct ata_port *ap, int attached) |
577 | { | 558 | { |
578 | void __iomem *port = ap->ioaddr.cmd_addr; | 559 | void __iomem *port = sil24_port_base(ap); |
579 | 560 | ||
580 | if (attached) | 561 | if (attached) |
581 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT); | 562 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT); |
@@ -585,7 +566,7 @@ static void sil24_config_pmp(struct ata_port *ap, int attached) | |||
585 | 566 | ||
586 | static void sil24_clear_pmp(struct ata_port *ap) | 567 | static void sil24_clear_pmp(struct ata_port *ap) |
587 | { | 568 | { |
588 | void __iomem *port = ap->ioaddr.cmd_addr; | 569 | void __iomem *port = sil24_port_base(ap); |
589 | int i; | 570 | int i; |
590 | 571 | ||
591 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); | 572 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); |
@@ -600,12 +581,12 @@ static void sil24_clear_pmp(struct ata_port *ap) | |||
600 | 581 | ||
601 | static int sil24_init_port(struct ata_port *ap) | 582 | static int sil24_init_port(struct ata_port *ap) |
602 | { | 583 | { |
603 | void __iomem *port = ap->ioaddr.cmd_addr; | 584 | void __iomem *port = sil24_port_base(ap); |
604 | struct sil24_port_priv *pp = ap->private_data; | 585 | struct sil24_port_priv *pp = ap->private_data; |
605 | u32 tmp; | 586 | u32 tmp; |
606 | 587 | ||
607 | /* clear PMP error status */ | 588 | /* clear PMP error status */ |
608 | if (ap->nr_pmp_links) | 589 | if (sata_pmp_attached(ap)) |
609 | sil24_clear_pmp(ap); | 590 | sil24_clear_pmp(ap); |
610 | 591 | ||
611 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); | 592 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); |
@@ -616,7 +597,7 @@ static int sil24_init_port(struct ata_port *ap) | |||
616 | 597 | ||
617 | if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) { | 598 | if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) { |
618 | pp->do_port_rst = 1; | 599 | pp->do_port_rst = 1; |
619 | ap->link.eh_context.i.action |= ATA_EH_HARDRESET; | 600 | ap->link.eh_context.i.action |= ATA_EH_RESET; |
620 | return -EIO; | 601 | return -EIO; |
621 | } | 602 | } |
622 | 603 | ||
@@ -628,7 +609,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
628 | int is_cmd, u32 ctrl, | 609 | int is_cmd, u32 ctrl, |
629 | unsigned long timeout_msec) | 610 | unsigned long timeout_msec) |
630 | { | 611 | { |
631 | void __iomem *port = ap->ioaddr.cmd_addr; | 612 | void __iomem *port = sil24_port_base(ap); |
632 | struct sil24_port_priv *pp = ap->private_data; | 613 | struct sil24_port_priv *pp = ap->private_data; |
633 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; | 614 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; |
634 | dma_addr_t paddr = pp->cmd_block_dma; | 615 | dma_addr_t paddr = pp->cmd_block_dma; |
@@ -670,10 +651,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
670 | return rc; | 651 | return rc; |
671 | } | 652 | } |
672 | 653 | ||
673 | static int sil24_do_softreset(struct ata_link *link, unsigned int *class, | 654 | static int sil24_softreset(struct ata_link *link, unsigned int *class, |
674 | int pmp, unsigned long deadline) | 655 | unsigned long deadline) |
675 | { | 656 | { |
676 | struct ata_port *ap = link->ap; | 657 | struct ata_port *ap = link->ap; |
658 | int pmp = sata_srst_pmp(link); | ||
677 | unsigned long timeout_msec = 0; | 659 | unsigned long timeout_msec = 0; |
678 | struct ata_taskfile tf; | 660 | struct ata_taskfile tf; |
679 | const char *reason; | 661 | const char *reason; |
@@ -681,12 +663,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, | |||
681 | 663 | ||
682 | DPRINTK("ENTER\n"); | 664 | DPRINTK("ENTER\n"); |
683 | 665 | ||
684 | if (ata_link_offline(link)) { | ||
685 | DPRINTK("PHY reports no device\n"); | ||
686 | *class = ATA_DEV_NONE; | ||
687 | goto out; | ||
688 | } | ||
689 | |||
690 | /* put the port into known state */ | 666 | /* put the port into known state */ |
691 | if (sil24_init_port(ap)) { | 667 | if (sil24_init_port(ap)) { |
692 | reason = "port not ready"; | 668 | reason = "port not ready"; |
@@ -711,10 +687,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, | |||
711 | sil24_read_tf(ap, 0, &tf); | 687 | sil24_read_tf(ap, 0, &tf); |
712 | *class = ata_dev_classify(&tf); | 688 | *class = ata_dev_classify(&tf); |
713 | 689 | ||
714 | if (*class == ATA_DEV_UNKNOWN) | ||
715 | *class = ATA_DEV_NONE; | ||
716 | |||
717 | out: | ||
718 | DPRINTK("EXIT, class=%u\n", *class); | 690 | DPRINTK("EXIT, class=%u\n", *class); |
719 | return 0; | 691 | return 0; |
720 | 692 | ||
@@ -723,17 +695,11 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, | |||
723 | return -EIO; | 695 | return -EIO; |
724 | } | 696 | } |
725 | 697 | ||
726 | static int sil24_softreset(struct ata_link *link, unsigned int *class, | ||
727 | unsigned long deadline) | ||
728 | { | ||
729 | return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline); | ||
730 | } | ||
731 | |||
732 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, | 698 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, |
733 | unsigned long deadline) | 699 | unsigned long deadline) |
734 | { | 700 | { |
735 | struct ata_port *ap = link->ap; | 701 | struct ata_port *ap = link->ap; |
736 | void __iomem *port = ap->ioaddr.cmd_addr; | 702 | void __iomem *port = sil24_port_base(ap); |
737 | struct sil24_port_priv *pp = ap->private_data; | 703 | struct sil24_port_priv *pp = ap->private_data; |
738 | int did_port_rst = 0; | 704 | int did_port_rst = 0; |
739 | const char *reason; | 705 | const char *reason; |
@@ -911,7 +877,7 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) | |||
911 | { | 877 | { |
912 | struct ata_port *ap = qc->ap; | 878 | struct ata_port *ap = qc->ap; |
913 | struct sil24_port_priv *pp = ap->private_data; | 879 | struct sil24_port_priv *pp = ap->private_data; |
914 | void __iomem *port = ap->ioaddr.cmd_addr; | 880 | void __iomem *port = sil24_port_base(ap); |
915 | unsigned int tag = sil24_tag(qc->tag); | 881 | unsigned int tag = sil24_tag(qc->tag); |
916 | dma_addr_t paddr; | 882 | dma_addr_t paddr; |
917 | void __iomem *activate; | 883 | void __iomem *activate; |
@@ -925,9 +891,10 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) | |||
925 | return 0; | 891 | return 0; |
926 | } | 892 | } |
927 | 893 | ||
928 | static void sil24_irq_clear(struct ata_port *ap) | 894 | static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc) |
929 | { | 895 | { |
930 | /* unused */ | 896 | sil24_read_tf(qc->ap, qc->tag, &qc->result_tf); |
897 | return true; | ||
931 | } | 898 | } |
932 | 899 | ||
933 | static void sil24_pmp_attach(struct ata_port *ap) | 900 | static void sil24_pmp_attach(struct ata_port *ap) |
@@ -942,12 +909,6 @@ static void sil24_pmp_detach(struct ata_port *ap) | |||
942 | sil24_config_pmp(ap, 0); | 909 | sil24_config_pmp(ap, 0); |
943 | } | 910 | } |
944 | 911 | ||
945 | static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class, | ||
946 | unsigned long deadline) | ||
947 | { | ||
948 | return sil24_do_softreset(link, class, link->pmp, deadline); | ||
949 | } | ||
950 | |||
951 | static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, | 912 | static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, |
952 | unsigned long deadline) | 913 | unsigned long deadline) |
953 | { | 914 | { |
@@ -960,12 +921,12 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, | |||
960 | return rc; | 921 | return rc; |
961 | } | 922 | } |
962 | 923 | ||
963 | return sata_pmp_std_hardreset(link, class, deadline); | 924 | return sata_std_hardreset(link, class, deadline); |
964 | } | 925 | } |
965 | 926 | ||
966 | static void sil24_freeze(struct ata_port *ap) | 927 | static void sil24_freeze(struct ata_port *ap) |
967 | { | 928 | { |
968 | void __iomem *port = ap->ioaddr.cmd_addr; | 929 | void __iomem *port = sil24_port_base(ap); |
969 | 930 | ||
970 | /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear | 931 | /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear |
971 | * PORT_IRQ_ENABLE instead. | 932 | * PORT_IRQ_ENABLE instead. |
@@ -975,7 +936,7 @@ static void sil24_freeze(struct ata_port *ap) | |||
975 | 936 | ||
976 | static void sil24_thaw(struct ata_port *ap) | 937 | static void sil24_thaw(struct ata_port *ap) |
977 | { | 938 | { |
978 | void __iomem *port = ap->ioaddr.cmd_addr; | 939 | void __iomem *port = sil24_port_base(ap); |
979 | u32 tmp; | 940 | u32 tmp; |
980 | 941 | ||
981 | /* clear IRQ */ | 942 | /* clear IRQ */ |
@@ -988,7 +949,7 @@ static void sil24_thaw(struct ata_port *ap) | |||
988 | 949 | ||
989 | static void sil24_error_intr(struct ata_port *ap) | 950 | static void sil24_error_intr(struct ata_port *ap) |
990 | { | 951 | { |
991 | void __iomem *port = ap->ioaddr.cmd_addr; | 952 | void __iomem *port = sil24_port_base(ap); |
992 | struct sil24_port_priv *pp = ap->private_data; | 953 | struct sil24_port_priv *pp = ap->private_data; |
993 | struct ata_queued_cmd *qc = NULL; | 954 | struct ata_queued_cmd *qc = NULL; |
994 | struct ata_link *link; | 955 | struct ata_link *link; |
@@ -1022,7 +983,7 @@ static void sil24_error_intr(struct ata_port *ap) | |||
1022 | 983 | ||
1023 | if (irq_stat & PORT_IRQ_UNK_FIS) { | 984 | if (irq_stat & PORT_IRQ_UNK_FIS) { |
1024 | ehi->err_mask |= AC_ERR_HSM; | 985 | ehi->err_mask |= AC_ERR_HSM; |
1025 | ehi->action |= ATA_EH_SOFTRESET; | 986 | ehi->action |= ATA_EH_RESET; |
1026 | ata_ehi_push_desc(ehi, "unknown FIS"); | 987 | ata_ehi_push_desc(ehi, "unknown FIS"); |
1027 | freeze = 1; | 988 | freeze = 1; |
1028 | } | 989 | } |
@@ -1043,14 +1004,14 @@ static void sil24_error_intr(struct ata_port *ap) | |||
1043 | */ | 1004 | */ |
1044 | if (ap->nr_active_links >= 3) { | 1005 | if (ap->nr_active_links >= 3) { |
1045 | ehi->err_mask |= AC_ERR_OTHER; | 1006 | ehi->err_mask |= AC_ERR_OTHER; |
1046 | ehi->action |= ATA_EH_HARDRESET; | 1007 | ehi->action |= ATA_EH_RESET; |
1047 | ata_ehi_push_desc(ehi, "PMP DMA CS errata"); | 1008 | ata_ehi_push_desc(ehi, "PMP DMA CS errata"); |
1048 | pp->do_port_rst = 1; | 1009 | pp->do_port_rst = 1; |
1049 | freeze = 1; | 1010 | freeze = 1; |
1050 | } | 1011 | } |
1051 | 1012 | ||
1052 | /* find out the offending link and qc */ | 1013 | /* find out the offending link and qc */ |
1053 | if (ap->nr_pmp_links) { | 1014 | if (sata_pmp_attached(ap)) { |
1054 | context = readl(port + PORT_CONTEXT); | 1015 | context = readl(port + PORT_CONTEXT); |
1055 | pmp = (context >> 5) & 0xf; | 1016 | pmp = (context >> 5) & 0xf; |
1056 | 1017 | ||
@@ -1064,7 +1025,7 @@ static void sil24_error_intr(struct ata_port *ap) | |||
1064 | irq_stat); | 1025 | irq_stat); |
1065 | } else { | 1026 | } else { |
1066 | err_mask |= AC_ERR_HSM; | 1027 | err_mask |= AC_ERR_HSM; |
1067 | action |= ATA_EH_HARDRESET; | 1028 | action |= ATA_EH_RESET; |
1068 | freeze = 1; | 1029 | freeze = 1; |
1069 | } | 1030 | } |
1070 | } else | 1031 | } else |
@@ -1078,28 +1039,27 @@ static void sil24_error_intr(struct ata_port *ap) | |||
1078 | if (ci && ci->desc) { | 1039 | if (ci && ci->desc) { |
1079 | err_mask |= ci->err_mask; | 1040 | err_mask |= ci->err_mask; |
1080 | action |= ci->action; | 1041 | action |= ci->action; |
1081 | if (action & ATA_EH_RESET_MASK) | 1042 | if (action & ATA_EH_RESET) |
1082 | freeze = 1; | 1043 | freeze = 1; |
1083 | ata_ehi_push_desc(ehi, "%s", ci->desc); | 1044 | ata_ehi_push_desc(ehi, "%s", ci->desc); |
1084 | } else { | 1045 | } else { |
1085 | err_mask |= AC_ERR_OTHER; | 1046 | err_mask |= AC_ERR_OTHER; |
1086 | action |= ATA_EH_SOFTRESET; | 1047 | action |= ATA_EH_RESET; |
1087 | freeze = 1; | 1048 | freeze = 1; |
1088 | ata_ehi_push_desc(ehi, "unknown command error %d", | 1049 | ata_ehi_push_desc(ehi, "unknown command error %d", |
1089 | cerr); | 1050 | cerr); |
1090 | } | 1051 | } |
1091 | 1052 | ||
1092 | /* record error info */ | 1053 | /* record error info */ |
1093 | if (qc) { | 1054 | if (qc) |
1094 | sil24_read_tf(ap, qc->tag, &pp->tf); | ||
1095 | qc->err_mask |= err_mask; | 1055 | qc->err_mask |= err_mask; |
1096 | } else | 1056 | else |
1097 | ehi->err_mask |= err_mask; | 1057 | ehi->err_mask |= err_mask; |
1098 | 1058 | ||
1099 | ehi->action |= action; | 1059 | ehi->action |= action; |
1100 | 1060 | ||
1101 | /* if PMP, resume */ | 1061 | /* if PMP, resume */ |
1102 | if (ap->nr_pmp_links) | 1062 | if (sata_pmp_attached(ap)) |
1103 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT); | 1063 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT); |
1104 | } | 1064 | } |
1105 | 1065 | ||
@@ -1114,18 +1074,9 @@ static void sil24_error_intr(struct ata_port *ap) | |||
1114 | } | 1074 | } |
1115 | } | 1075 | } |
1116 | 1076 | ||
1117 | static void sil24_finish_qc(struct ata_queued_cmd *qc) | ||
1118 | { | ||
1119 | struct ata_port *ap = qc->ap; | ||
1120 | struct sil24_port_priv *pp = ap->private_data; | ||
1121 | |||
1122 | if (qc->flags & ATA_QCFLAG_RESULT_TF) | ||
1123 | sil24_read_tf(ap, qc->tag, &pp->tf); | ||
1124 | } | ||
1125 | |||
1126 | static inline void sil24_host_intr(struct ata_port *ap) | 1077 | static inline void sil24_host_intr(struct ata_port *ap) |
1127 | { | 1078 | { |
1128 | void __iomem *port = ap->ioaddr.cmd_addr; | 1079 | void __iomem *port = sil24_port_base(ap); |
1129 | u32 slot_stat, qc_active; | 1080 | u32 slot_stat, qc_active; |
1130 | int rc; | 1081 | int rc; |
1131 | 1082 | ||
@@ -1147,13 +1098,13 @@ static inline void sil24_host_intr(struct ata_port *ap) | |||
1147 | } | 1098 | } |
1148 | 1099 | ||
1149 | qc_active = slot_stat & ~HOST_SSTAT_ATTN; | 1100 | qc_active = slot_stat & ~HOST_SSTAT_ATTN; |
1150 | rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); | 1101 | rc = ata_qc_complete_multiple(ap, qc_active); |
1151 | if (rc > 0) | 1102 | if (rc > 0) |
1152 | return; | 1103 | return; |
1153 | if (rc < 0) { | 1104 | if (rc < 0) { |
1154 | struct ata_eh_info *ehi = &ap->link.eh_info; | 1105 | struct ata_eh_info *ehi = &ap->link.eh_info; |
1155 | ehi->err_mask |= AC_ERR_HSM; | 1106 | ehi->err_mask |= AC_ERR_HSM; |
1156 | ehi->action |= ATA_EH_SOFTRESET; | 1107 | ehi->action |= ATA_EH_RESET; |
1157 | ata_port_freeze(ap); | 1108 | ata_port_freeze(ap); |
1158 | return; | 1109 | return; |
1159 | } | 1110 | } |
@@ -1209,11 +1160,7 @@ static void sil24_error_handler(struct ata_port *ap) | |||
1209 | if (sil24_init_port(ap)) | 1160 | if (sil24_init_port(ap)) |
1210 | ata_eh_freeze_port(ap); | 1161 | ata_eh_freeze_port(ap); |
1211 | 1162 | ||
1212 | /* perform recovery */ | 1163 | sata_pmp_error_handler(ap); |
1213 | sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, | ||
1214 | ata_std_postreset, sata_pmp_std_prereset, | ||
1215 | sil24_pmp_softreset, sil24_pmp_hardreset, | ||
1216 | sata_pmp_std_postreset); | ||
1217 | 1164 | ||
1218 | pp->do_port_rst = 0; | 1165 | pp->do_port_rst = 0; |
1219 | } | 1166 | } |
@@ -1239,8 +1186,6 @@ static int sil24_port_start(struct ata_port *ap) | |||
1239 | if (!pp) | 1186 | if (!pp) |
1240 | return -ENOMEM; | 1187 | return -ENOMEM; |
1241 | 1188 | ||
1242 | pp->tf.command = ATA_DRDY; | ||
1243 | |||
1244 | cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); | 1189 | cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); |
1245 | if (!cb) | 1190 | if (!cb) |
1246 | return -ENOMEM; | 1191 | return -ENOMEM; |
@@ -1251,6 +1196,9 @@ static int sil24_port_start(struct ata_port *ap) | |||
1251 | 1196 | ||
1252 | ap->private_data = pp; | 1197 | ap->private_data = pp; |
1253 | 1198 | ||
1199 | ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host"); | ||
1200 | ata_port_pbar_desc(ap, SIL24_PORT_BAR, sil24_port_offset(ap), "port"); | ||
1201 | |||
1254 | return 0; | 1202 | return 0; |
1255 | } | 1203 | } |
1256 | 1204 | ||
@@ -1269,7 +1217,8 @@ static void sil24_init_controller(struct ata_host *host) | |||
1269 | /* init ports */ | 1217 | /* init ports */ |
1270 | for (i = 0; i < host->n_ports; i++) { | 1218 | for (i = 0; i < host->n_ports; i++) { |
1271 | struct ata_port *ap = host->ports[i]; | 1219 | struct ata_port *ap = host->ports[i]; |
1272 | void __iomem *port = ap->ioaddr.cmd_addr; | 1220 | void __iomem *port = sil24_port_base(ap); |
1221 | |||
1273 | 1222 | ||
1274 | /* Initial PHY setting */ | 1223 | /* Initial PHY setting */ |
1275 | writel(0x20c, port + PORT_PHY_CFG); | 1224 | writel(0x20c, port + PORT_PHY_CFG); |
@@ -1302,7 +1251,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1302 | const struct ata_port_info *ppi[] = { &pi, NULL }; | 1251 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
1303 | void __iomem * const *iomap; | 1252 | void __iomem * const *iomap; |
1304 | struct ata_host *host; | 1253 | struct ata_host *host; |
1305 | int i, rc; | 1254 | int rc; |
1306 | u32 tmp; | 1255 | u32 tmp; |
1307 | 1256 | ||
1308 | /* cause link error if sil24_cmd_block is sized wrongly */ | 1257 | /* cause link error if sil24_cmd_block is sized wrongly */ |
@@ -1342,18 +1291,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1342 | return -ENOMEM; | 1291 | return -ENOMEM; |
1343 | host->iomap = iomap; | 1292 | host->iomap = iomap; |
1344 | 1293 | ||
1345 | for (i = 0; i < host->n_ports; i++) { | ||
1346 | struct ata_port *ap = host->ports[i]; | ||
1347 | size_t offset = ap->port_no * PORT_REGS_SIZE; | ||
1348 | void __iomem *port = iomap[SIL24_PORT_BAR] + offset; | ||
1349 | |||
1350 | host->ports[i]->ioaddr.cmd_addr = port; | ||
1351 | host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL; | ||
1352 | |||
1353 | ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host"); | ||
1354 | ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port"); | ||
1355 | } | ||
1356 | |||
1357 | /* configure and activate the device */ | 1294 | /* configure and activate the device */ |
1358 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { | 1295 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { |
1359 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | 1296 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); |