diff options
| author | Tejun Heo <htejun@gmail.com> | 2006-08-10 03:59:12 -0400 |
|---|---|---|
| committer | Tejun Heo <htejun@gmail.com> | 2006-08-10 03:59:12 -0400 |
| commit | dd5b06c490de72440ec39f814de99a714a45a1a9 (patch) | |
| tree | 7a4665f9b6fdb5a264c753b90a215e2953e2d0f7 | |
| parent | 2ec7df0457b710d9201f211dbccdbecf0ad38b7e (diff) | |
[PATCH] libata: implement dummy port
Implement dummy port which can be requested by setting appropriate bit
in probe_ent->dummy_port_mask. The dummy port is used as placeholder
for stolen legacy port. This allows libata to guarantee that
index_of(ap) == ap->port_no == actual_device_port_no, and thus to
remove error-prone ap->hard_port_no.
As it's used only when one port of a legacy controller is reserved by
some other entity (e.g. IDE), the focus is on keeping the added *code*
complexity at minimum, so dummy port allocates all libata core
resources and acts as a normal port. It just has all dummy port_ops.
This patch only implements dummy port. The following patch will make
libata use it for stolen legacy ports.
Signed-off-by: Tejun Heo <htejun@gmail.com>
| -rw-r--r-- | drivers/scsi/libata-core.c | 61 | ||||
| -rw-r--r-- | include/linux/libata.h | 8 |
2 files changed, 59 insertions, 10 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3634279d896d..f2e7e2f13db9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -5311,7 +5311,6 @@ static struct ata_port * ata_port_add(const struct ata_probe_ent *ent, | |||
| 5311 | { | 5311 | { |
| 5312 | struct Scsi_Host *shost; | 5312 | struct Scsi_Host *shost; |
| 5313 | struct ata_port *ap; | 5313 | struct ata_port *ap; |
| 5314 | int rc; | ||
| 5315 | 5314 | ||
| 5316 | DPRINTK("ENTER\n"); | 5315 | DPRINTK("ENTER\n"); |
| 5317 | 5316 | ||
| @@ -5333,15 +5332,7 @@ static struct ata_port * ata_port_add(const struct ata_probe_ent *ent, | |||
| 5333 | ata_port_init(ap, host_set, ent, port_no); | 5332 | ata_port_init(ap, host_set, ent, port_no); |
| 5334 | ata_port_init_shost(ap, shost); | 5333 | ata_port_init_shost(ap, shost); |
| 5335 | 5334 | ||
| 5336 | rc = ap->ops->port_start(ap); | ||
| 5337 | if (rc) | ||
| 5338 | goto err_out; | ||
| 5339 | |||
| 5340 | return ap; | 5335 | return ap; |
| 5341 | |||
| 5342 | err_out: | ||
| 5343 | scsi_host_put(shost); | ||
| 5344 | return NULL; | ||
| 5345 | } | 5336 | } |
| 5346 | 5337 | ||
| 5347 | /** | 5338 | /** |
| @@ -5415,11 +5406,27 @@ int ata_device_add(const struct ata_probe_ent *ent) | |||
| 5415 | if (!ap) | 5406 | if (!ap) |
| 5416 | goto err_out; | 5407 | goto err_out; |
| 5417 | 5408 | ||
| 5409 | host_set->ports[i] = ap; | ||
| 5410 | |||
| 5411 | /* dummy? */ | ||
| 5412 | if (ent->dummy_port_mask & (1 << i)) { | ||
| 5413 | ata_port_printk(ap, KERN_INFO, "DUMMY\n"); | ||
| 5414 | ap->ops = &ata_dummy_port_ops; | ||
| 5415 | continue; | ||
| 5416 | } | ||
| 5417 | |||
| 5418 | /* start port */ | ||
| 5419 | rc = ap->ops->port_start(ap); | ||
| 5420 | if (rc) { | ||
| 5421 | host_set->ports[i] = NULL; | ||
| 5422 | scsi_host_put(ap->host); | ||
| 5423 | goto err_out; | ||
| 5424 | } | ||
| 5425 | |||
| 5418 | /* Report the secondary IRQ for second channel legacy */ | 5426 | /* Report the secondary IRQ for second channel legacy */ |
| 5419 | if (i == 1 && ent->irq2) | 5427 | if (i == 1 && ent->irq2) |
| 5420 | irq_line = ent->irq2; | 5428 | irq_line = ent->irq2; |
| 5421 | 5429 | ||
| 5422 | host_set->ports[i] = ap; | ||
| 5423 | xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | | 5430 | xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | |
| 5424 | (ap->mwdma_mask << ATA_SHIFT_MWDMA) | | 5431 | (ap->mwdma_mask << ATA_SHIFT_MWDMA) | |
| 5425 | (ap->pio_mask << ATA_SHIFT_PIO); | 5432 | (ap->pio_mask << ATA_SHIFT_PIO); |
| @@ -5941,6 +5948,39 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, | |||
| 5941 | } | 5948 | } |
| 5942 | 5949 | ||
| 5943 | /* | 5950 | /* |
| 5951 | * Dummy port_ops | ||
| 5952 | */ | ||
| 5953 | static void ata_dummy_noret(struct ata_port *ap) { } | ||
| 5954 | static int ata_dummy_ret0(struct ata_port *ap) { return 0; } | ||
| 5955 | static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { } | ||
| 5956 | |||
| 5957 | static u8 ata_dummy_check_status(struct ata_port *ap) | ||
| 5958 | { | ||
| 5959 | return ATA_DRDY; | ||
| 5960 | } | ||
| 5961 | |||
| 5962 | static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc) | ||
| 5963 | { | ||
| 5964 | return AC_ERR_SYSTEM; | ||
| 5965 | } | ||
| 5966 | |||
| 5967 | const struct ata_port_operations ata_dummy_port_ops = { | ||
| 5968 | .port_disable = ata_port_disable, | ||
| 5969 | .check_status = ata_dummy_check_status, | ||
| 5970 | .check_altstatus = ata_dummy_check_status, | ||
| 5971 | .dev_select = ata_noop_dev_select, | ||
| 5972 | .qc_prep = ata_noop_qc_prep, | ||
| 5973 | .qc_issue = ata_dummy_qc_issue, | ||
| 5974 | .freeze = ata_dummy_noret, | ||
| 5975 | .thaw = ata_dummy_noret, | ||
| 5976 | .error_handler = ata_dummy_noret, | ||
| 5977 | .post_internal_cmd = ata_dummy_qc_noret, | ||
| 5978 | .irq_clear = ata_dummy_noret, | ||
| 5979 | .port_start = ata_dummy_ret0, | ||
| 5980 | .port_stop = ata_dummy_noret, | ||
| 5981 | }; | ||
| 5982 | |||
| 5983 | /* | ||
| 5944 | * libata is essentially a library of internal helper functions for | 5984 | * libata is essentially a library of internal helper functions for |
| 5945 | * low-level ATA host controller drivers. As such, the API/ABI is | 5985 | * low-level ATA host controller drivers. As such, the API/ABI is |
| 5946 | * likely to change as new drivers are added and updated. | 5986 | * likely to change as new drivers are added and updated. |
| @@ -5950,6 +5990,7 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, | |||
| 5950 | EXPORT_SYMBOL_GPL(sata_deb_timing_normal); | 5990 | EXPORT_SYMBOL_GPL(sata_deb_timing_normal); |
| 5951 | EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); | 5991 | EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); |
| 5952 | EXPORT_SYMBOL_GPL(sata_deb_timing_long); | 5992 | EXPORT_SYMBOL_GPL(sata_deb_timing_long); |
| 5993 | EXPORT_SYMBOL_GPL(ata_dummy_port_ops); | ||
| 5953 | EXPORT_SYMBOL_GPL(ata_std_bios_param); | 5994 | EXPORT_SYMBOL_GPL(ata_std_bios_param); |
| 5954 | EXPORT_SYMBOL_GPL(ata_std_ports); | 5995 | EXPORT_SYMBOL_GPL(ata_std_ports); |
| 5955 | EXPORT_SYMBOL_GPL(ata_host_set_init); | 5996 | EXPORT_SYMBOL_GPL(ata_host_set_init); |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 4504776570e4..30bfe8f1666e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -353,6 +353,7 @@ struct ata_probe_ent { | |||
| 353 | struct ata_ioports port[ATA_MAX_PORTS]; | 353 | struct ata_ioports port[ATA_MAX_PORTS]; |
| 354 | unsigned int n_ports; | 354 | unsigned int n_ports; |
| 355 | unsigned int hard_port_no; | 355 | unsigned int hard_port_no; |
| 356 | unsigned int dummy_port_mask; | ||
| 356 | unsigned int pio_mask; | 357 | unsigned int pio_mask; |
| 357 | unsigned int mwdma_mask; | 358 | unsigned int mwdma_mask; |
| 358 | unsigned int udma_mask; | 359 | unsigned int udma_mask; |
| @@ -652,6 +653,8 @@ extern const unsigned long sata_deb_timing_normal[]; | |||
| 652 | extern const unsigned long sata_deb_timing_hotplug[]; | 653 | extern const unsigned long sata_deb_timing_hotplug[]; |
| 653 | extern const unsigned long sata_deb_timing_long[]; | 654 | extern const unsigned long sata_deb_timing_long[]; |
| 654 | 655 | ||
| 656 | extern const struct ata_port_operations ata_dummy_port_ops; | ||
| 657 | |||
| 655 | static inline const unsigned long * | 658 | static inline const unsigned long * |
| 656 | sata_ehc_deb_timing(struct ata_eh_context *ehc) | 659 | sata_ehc_deb_timing(struct ata_eh_context *ehc) |
| 657 | { | 660 | { |
| @@ -661,6 +664,11 @@ sata_ehc_deb_timing(struct ata_eh_context *ehc) | |||
| 661 | return sata_deb_timing_normal; | 664 | return sata_deb_timing_normal; |
| 662 | } | 665 | } |
| 663 | 666 | ||
| 667 | static inline int ata_port_is_dummy(struct ata_port *ap) | ||
| 668 | { | ||
| 669 | return ap->ops == &ata_dummy_port_ops; | ||
| 670 | } | ||
| 671 | |||
| 664 | extern void ata_port_probe(struct ata_port *); | 672 | extern void ata_port_probe(struct ata_port *); |
| 665 | extern void __sata_phy_reset(struct ata_port *ap); | 673 | extern void __sata_phy_reset(struct ata_port *ap); |
| 666 | extern void sata_phy_reset(struct ata_port *ap); | 674 | extern void sata_phy_reset(struct ata_port *ap); |
