Commit e3cf95dd6d352954b663d2934110d6e30af2406d
Committed by
Jeff Garzik
1 parent
62afe5d744
Exists in
master
and in
39 other branches
ata: Report 16/32bit PIO as best we can
The legacy old IDE ioctl API for this is a bit primitive so we try and map stuff sensibly onto it. - Set PIO over DMA devices to report 32bit - Add ability to change the PIO32 settings if the controller permits it - Add that functionality into the sff drivers - Add that functionality into the VLB legacy driver - Turn on the 32bit PIO on the ninja32 and add support there Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Showing 5 changed files with 84 additions and 18 deletions Side-by-side Diff
drivers/ata/libata-scsi.c
... | ... | @@ -647,23 +647,45 @@ |
647 | 647 | return rc; |
648 | 648 | } |
649 | 649 | |
650 | +static int ata_ioc32(struct ata_port *ap) | |
651 | +{ | |
652 | + if (ap->flags & ATA_FLAG_PIO_DMA) | |
653 | + return 1; | |
654 | + if (ap->pflags & ATA_PFLAG_PIO32) | |
655 | + return 1; | |
656 | + return 0; | |
657 | +} | |
658 | + | |
650 | 659 | int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, |
651 | 660 | int cmd, void __user *arg) |
652 | 661 | { |
653 | 662 | int val = -EINVAL, rc = -EINVAL; |
663 | + unsigned long flags; | |
654 | 664 | |
655 | 665 | switch (cmd) { |
656 | 666 | case ATA_IOC_GET_IO32: |
657 | - val = 0; | |
667 | + spin_lock_irqsave(ap->lock, flags); | |
668 | + val = ata_ioc32(ap); | |
669 | + spin_unlock_irqrestore(ap->lock, flags); | |
658 | 670 | if (copy_to_user(arg, &val, 1)) |
659 | 671 | return -EFAULT; |
660 | 672 | return 0; |
661 | 673 | |
662 | 674 | case ATA_IOC_SET_IO32: |
663 | 675 | val = (unsigned long) arg; |
664 | - if (val != 0) | |
665 | - return -EINVAL; | |
666 | - return 0; | |
676 | + rc = 0; | |
677 | + spin_lock_irqsave(ap->lock, flags); | |
678 | + if (ap->pflags & ATA_PFLAG_PIO32CHANGE) { | |
679 | + if (val) | |
680 | + ap->pflags |= ATA_PFLAG_PIO32; | |
681 | + else | |
682 | + ap->pflags &= ~ATA_PFLAG_PIO32; | |
683 | + } else { | |
684 | + if (val != ata_ioc32(ap)) | |
685 | + rc = -EINVAL; | |
686 | + } | |
687 | + spin_unlock_irqrestore(ap->lock, flags); | |
688 | + return rc; | |
667 | 689 | |
668 | 690 | case HDIO_GET_IDENTITY: |
669 | 691 | return ata_get_identity(ap, scsidev, arg); |
drivers/ata/libata-sff.c
... | ... | @@ -87,6 +87,7 @@ |
87 | 87 | .inherits = &ata_bmdma_port_ops, |
88 | 88 | |
89 | 89 | .sff_data_xfer = ata_sff_data_xfer32, |
90 | + .port_start = ata_sff_port_start32, | |
90 | 91 | }; |
91 | 92 | EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops); |
92 | 93 | |
... | ... | @@ -769,6 +770,9 @@ |
769 | 770 | void __iomem *data_addr = ap->ioaddr.data_addr; |
770 | 771 | unsigned int words = buflen >> 2; |
771 | 772 | int slop = buflen & 3; |
773 | + | |
774 | + if (!(ap->pflags & ATA_PFLAG_PIO32)) | |
775 | + return ata_sff_data_xfer(dev, buf, buflen, rw); | |
772 | 776 | |
773 | 777 | /* Transfer multiple of 4 bytes */ |
774 | 778 | if (rw == READ) |
... | ... | @@ -2400,6 +2404,29 @@ |
2400 | 2404 | return 0; |
2401 | 2405 | } |
2402 | 2406 | EXPORT_SYMBOL_GPL(ata_sff_port_start); |
2407 | + | |
2408 | +/** | |
2409 | + * ata_sff_port_start32 - Set port up for dma. | |
2410 | + * @ap: Port to initialize | |
2411 | + * | |
2412 | + * Called just after data structures for each port are | |
2413 | + * initialized. Allocates space for PRD table if the device | |
2414 | + * is DMA capable SFF. | |
2415 | + * | |
2416 | + * May be used as the port_start() entry in ata_port_operations for | |
2417 | + * devices that are capable of 32bit PIO. | |
2418 | + * | |
2419 | + * LOCKING: | |
2420 | + * Inherited from caller. | |
2421 | + */ | |
2422 | +int ata_sff_port_start32(struct ata_port *ap) | |
2423 | +{ | |
2424 | + ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE; | |
2425 | + if (ap->ioaddr.bmdma_addr) | |
2426 | + return ata_port_start(ap); | |
2427 | + return 0; | |
2428 | +} | |
2429 | +EXPORT_SYMBOL_GPL(ata_sff_port_start32); | |
2403 | 2430 | |
2404 | 2431 | /** |
2405 | 2432 | * ata_sff_std_ports - initialize ioaddr with standard port offsets. |
drivers/ata/pata_legacy.c
... | ... | @@ -108,6 +108,7 @@ |
108 | 108 | struct ata_port_operations *ops; |
109 | 109 | unsigned int pio_mask; |
110 | 110 | unsigned int flags; |
111 | + unsigned int pflags; | |
111 | 112 | int (*setup)(struct platform_device *, struct legacy_probe *probe, |
112 | 113 | struct legacy_data *data); |
113 | 114 | }; |
... | ... | @@ -285,7 +286,8 @@ |
285 | 286 | { |
286 | 287 | int slop = buflen & 3; |
287 | 288 | /* 32bit I/O capable *and* we need to write a whole number of dwords */ |
288 | - if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) { | |
289 | + if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3) | |
290 | + && (ap->pflags & ATA_PFLAG_PIO32)) { | |
289 | 291 | struct ata_port *ap = dev->link->ap; |
290 | 292 | unsigned long flags; |
291 | 293 | |
... | ... | @@ -736,7 +738,8 @@ |
736 | 738 | struct ata_port *ap = adev->link->ap; |
737 | 739 | int slop = buflen & 3; |
738 | 740 | |
739 | - if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) { | |
741 | + if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3) | |
742 | + && (ap->pflags & ATA_PFLAG_PIO32)) { | |
740 | 743 | if (rw == WRITE) |
741 | 744 | iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); |
742 | 745 | else |
743 | 746 | |
744 | 747 | |
745 | 748 | |
746 | 749 | |
747 | 750 | |
748 | 751 | |
749 | 752 | |
750 | 753 | |
751 | 754 | |
752 | 755 | |
... | ... | @@ -858,27 +861,30 @@ |
858 | 861 | |
859 | 862 | static struct legacy_controller controllers[] = { |
860 | 863 | {"BIOS", &legacy_port_ops, 0x1F, |
861 | - ATA_FLAG_NO_IORDY, NULL }, | |
864 | + ATA_FLAG_NO_IORDY, 0, NULL }, | |
862 | 865 | {"Snooping", &simple_port_ops, 0x1F, |
863 | - 0 , NULL }, | |
866 | + 0, 0, NULL }, | |
864 | 867 | {"PDC20230", &pdc20230_port_ops, 0x7, |
865 | - ATA_FLAG_NO_IORDY, NULL }, | |
868 | + ATA_FLAG_NO_IORDY, | |
869 | + ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32_CHANGE, NULL }, | |
866 | 870 | {"HT6560A", &ht6560a_port_ops, 0x07, |
867 | - ATA_FLAG_NO_IORDY, NULL }, | |
871 | + ATA_FLAG_NO_IORDY, 0, NULL }, | |
868 | 872 | {"HT6560B", &ht6560b_port_ops, 0x1F, |
869 | - ATA_FLAG_NO_IORDY, NULL }, | |
873 | + ATA_FLAG_NO_IORDY, 0, NULL }, | |
870 | 874 | {"OPTI82C611A", &opti82c611a_port_ops, 0x0F, |
871 | - 0 , NULL }, | |
875 | + 0, 0, NULL }, | |
872 | 876 | {"OPTI82C46X", &opti82c46x_port_ops, 0x0F, |
873 | - 0 , NULL }, | |
877 | + 0, 0, NULL }, | |
874 | 878 | {"QDI6500", &qdi6500_port_ops, 0x07, |
875 | - ATA_FLAG_NO_IORDY, qdi_port }, | |
879 | + ATA_FLAG_NO_IORDY, | |
880 | + ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32_CHANGE, qdi_port }, | |
876 | 881 | {"QDI6580", &qdi6580_port_ops, 0x1F, |
877 | - 0 , qdi_port }, | |
882 | + 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32_CHANGE, qdi_port }, | |
878 | 883 | {"QDI6580DP", &qdi6580dp_port_ops, 0x1F, |
879 | - 0 , qdi_port }, | |
884 | + 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32_CHANGE, qdi_port }, | |
880 | 885 | {"W83759A", &winbond_port_ops, 0x1F, |
881 | - 0 , winbond_port } | |
886 | + 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32_CHANGE, | |
887 | + winbond_port } | |
882 | 888 | }; |
883 | 889 | |
884 | 890 | /** |
... | ... | @@ -1008,6 +1014,7 @@ |
1008 | 1014 | ap->ops = ops; |
1009 | 1015 | ap->pio_mask = pio_modes; |
1010 | 1016 | ap->flags |= ATA_FLAG_SLAVE_POSS | iordy; |
1017 | + ap->pflags |= controller->pflags; | |
1011 | 1018 | ap->ioaddr.cmd_addr = io_addr; |
1012 | 1019 | ap->ioaddr.altstatus_addr = ctrl_addr; |
1013 | 1020 | ap->ioaddr.ctl_addr = ctrl_addr; |
drivers/ata/pata_ninja32.c
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | #include <linux/libata.h> |
45 | 45 | |
46 | 46 | #define DRV_NAME "pata_ninja32" |
47 | -#define DRV_VERSION "0.1.3" | |
47 | +#define DRV_VERSION "0.1.5" | |
48 | 48 | |
49 | 49 | |
50 | 50 | /** |
... | ... | @@ -86,6 +86,7 @@ |
86 | 86 | .sff_dev_select = ninja32_dev_select, |
87 | 87 | .cable_detect = ata_cable_40wire, |
88 | 88 | .set_piomode = ninja32_set_piomode, |
89 | + .sff_data_xfer = ata_sff_data_xfer32 | |
89 | 90 | }; |
90 | 91 | |
91 | 92 | static void ninja32_program(void __iomem *base) |
... | ... | @@ -144,6 +145,7 @@ |
144 | 145 | ap->ioaddr.altstatus_addr = base + 0x1E; |
145 | 146 | ap->ioaddr.bmdma_addr = base; |
146 | 147 | ata_sff_std_ports(&ap->ioaddr); |
148 | + ap->pflags = ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE; | |
147 | 149 | |
148 | 150 | ninja32_program(base); |
149 | 151 | /* FIXME: Should we disable them at remove ? */ |
include/linux/libata.h
... | ... | @@ -209,6 +209,7 @@ |
209 | 209 | |
210 | 210 | /* bits 24:31 of ap->flags are reserved for LLD specific flags */ |
211 | 211 | |
212 | + | |
212 | 213 | /* struct ata_port pflags */ |
213 | 214 | ATA_PFLAG_EH_PENDING = (1 << 0), /* EH pending */ |
214 | 215 | ATA_PFLAG_EH_IN_PROGRESS = (1 << 1), /* EH in progress */ |
... | ... | @@ -225,6 +226,9 @@ |
225 | 226 | ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ |
226 | 227 | ATA_PFLAG_INIT_GTM_VALID = (1 << 19), /* initial gtm data valid */ |
227 | 228 | |
229 | + ATA_PFLAG_PIO32 = (1 << 20), /* 32bit PIO */ | |
230 | + ATA_PFLAG_PIO32CHANGE = (1 << 21), /* 32bit PIO can be turned on/off */ | |
231 | + | |
228 | 232 | /* struct ata_queued_cmd flags */ |
229 | 233 | ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ |
230 | 234 | ATA_QCFLAG_DMAMAP = (1 << 1), /* SG table is DMA mapped */ |
231 | 235 | |
... | ... | @@ -689,7 +693,10 @@ |
689 | 693 | struct Scsi_Host *scsi_host; /* our co-allocated scsi host */ |
690 | 694 | struct ata_port_operations *ops; |
691 | 695 | spinlock_t *lock; |
696 | + /* Flags owned by the EH context. Only EH should touch these once the | |
697 | + port is active */ | |
692 | 698 | unsigned long flags; /* ATA_FLAG_xxx */ |
699 | + /* Flags that change dynamically, protected by ap->lock */ | |
693 | 700 | unsigned int pflags; /* ATA_PFLAG_xxx */ |
694 | 701 | unsigned int print_id; /* user visible unique port ID */ |
695 | 702 | unsigned int port_no; /* 0 based port no. inside the host */ |
... | ... | @@ -1595,6 +1602,7 @@ |
1595 | 1602 | extern void ata_sff_error_handler(struct ata_port *ap); |
1596 | 1603 | extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc); |
1597 | 1604 | extern int ata_sff_port_start(struct ata_port *ap); |
1605 | +extern int ata_sff_port_start32(struct ata_port *ap); | |
1598 | 1606 | extern void ata_sff_std_ports(struct ata_ioports *ioaddr); |
1599 | 1607 | extern unsigned long ata_bmdma_mode_filter(struct ata_device *dev, |
1600 | 1608 | unsigned long xfer_mask); |