Browse Source

libata: implement ATA_FLAG_IGN_SIMPLEX and use it in sata_uli

Some uli controllers have stuck SIMPLEX bit which can't be cleared
with ata_pci_clear_simplex(), but the controller is capable of doing
DMAs on both channels simultaneously.  Implement ATA_FLAG_IGN_SIMPLEX
which makes libata ignore the simplex bit and use it in sata_uli.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Tejun Heo 18 years ago
parent
commit
b2a8bbe67d
3 changed files with 11 additions and 5 deletions
  1. 8 4
      drivers/ata/libata-sff.c
  2. 2 1
      drivers/ata/sata_uli.c
  3. 1 0
      include/linux/libata.h

+ 8 - 4
drivers/ata/libata-sff.c

@@ -870,7 +870,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
 			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
 			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
 		bmdma = pci_resource_start(pdev, 4);
 		bmdma = pci_resource_start(pdev, 4);
 		if (bmdma) {
 		if (bmdma) {
-			if (inb(bmdma + 2) & 0x80)
+			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 			probe_ent->port[p].bmdma_addr = bmdma;
 			probe_ent->port[p].bmdma_addr = bmdma;
 		}
 		}
@@ -886,7 +887,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
 		bmdma = pci_resource_start(pdev, 4);
 		bmdma = pci_resource_start(pdev, 4);
 		if (bmdma) {
 		if (bmdma) {
 			bmdma += 8;
 			bmdma += 8;
-			if(inb(bmdma + 2) & 0x80)
+			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 			probe_ent->port[p].bmdma_addr = bmdma;
 			probe_ent->port[p].bmdma_addr = bmdma;
 		}
 		}
@@ -920,7 +922,8 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
 		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
 		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
 		if (bmdma) {
 		if (bmdma) {
 			probe_ent->port[0].bmdma_addr = bmdma;
 			probe_ent->port[0].bmdma_addr = bmdma;
-			if (inb(bmdma + 2) & 0x80)
+			if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		}
 		ata_std_ports(&probe_ent->port[0]);
 		ata_std_ports(&probe_ent->port[0]);
@@ -937,7 +940,8 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
 		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
 		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
 		if (bmdma) {
 		if (bmdma) {
 			probe_ent->port[1].bmdma_addr = bmdma + 8;
 			probe_ent->port[1].bmdma_addr = bmdma + 8;
-			if (inb(bmdma + 10) & 0x80)
+			if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 10) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		}
 		ata_std_ports(&probe_ent->port[1]);
 		ata_std_ports(&probe_ent->port[1]);

+ 2 - 1
drivers/ata/sata_uli.c

@@ -128,7 +128,8 @@ static const struct ata_port_operations uli_ops = {
 
 
 static struct ata_port_info uli_port_info = {
 static struct ata_port_info uli_port_info = {
 	.sht            = &uli_sht,
 	.sht            = &uli_sht,
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+			  ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = 0x1f,		/* pio0-4 */
 	.pio_mask       = 0x1f,		/* pio0-4 */
 	.udma_mask      = 0x7f,		/* udma0-6 */
 	.udma_mask      = 0x7f,		/* udma0-6 */
 	.port_ops       = &uli_ops,
 	.port_ops       = &uli_ops,

+ 1 - 0
include/linux/libata.h

@@ -177,6 +177,7 @@ enum {
 					      * Register FIS clearing BSY */
 					      * Register FIS clearing BSY */
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
 	ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
 	ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
 
 
 	/* The following flag belongs to ap->pflags but is kept in
 	/* The following flag belongs to ap->pflags but is kept in
 	 * ap->flags because it's referenced in many LLDs and will be
 	 * ap->flags because it's referenced in many LLDs and will be