Re: [RFC] libata IORDY handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello.

Alan wrote:

It's sad to say but there's another bug in this function (even a regression from drivers/ide/pci/siimage.c) -- the 16-bit IORDY is not enabled when setting PIO mode (there's code that twiddles IORDY enable but that's actually only for *taskfile* accesses, 16-bit IORDY is controlled by the same PCI config. registers 80h/84h that enable DMA/UDMA transfer on SiI 680).

Fixed - also fixed clearing the bits when going into PIO mode from DMA,
which fixes a potential DMA changedown bug.

    Yeah, this is an issue in siimage.c...

Also redone the iordy stuff as your emails reminded me that it needed
finishing off and sorting out.

    Atttaching my (already obsolete) patch, just in case...

Alan

MBR, Sergei

Index: linux-2.6/drivers/ata/pata_sil680.c
===================================================================
--- linux-2.6.orig/drivers/ata/pata_sil680.c
+++ linux-2.6/drivers/ata/pata_sil680.c
@@ -139,9 +139,12 @@ static void sil680_set_piomode(struct at
 
 	unsigned long tfaddr = sil680_selreg(ap, 0x02);
 	unsigned long addr = sil680_seldev(ap, adev, 0x04);
+	unsigned long addr_mask = 0x80 + 4 * ap->port_no;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port_shift = adev->devno * 4;
 	int pio = adev->pio_mode - XFER_PIO_0;
 	int lowest_pio = pio;
+	u8  mode;
 	u16 reg;
 
 	struct ata_device *pair = ata_dev_pair(adev);
@@ -152,11 +155,31 @@ static void sil680_set_piomode(struct at
 	pci_write_config_word(pdev, addr, speed_p[pio]);
 	pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]);
 
-	pci_read_config_word(pdev, tfaddr-2, &reg);
-	reg &= ~0x0200;			/* Clear IORDY */
+	/*
+	 * Let's see if we need to enable IORDY checking on data transfer...
+	 *
+	 * NOTE: Selecting any DMA mode also enables IORDY  checkign,
+	 * so we must first check if not already in DMA mode beforehand
+	 * to avoid disabling it...
+	 */
+	pci_read_config_byte(pdev, addr_mask, &mode);
+	if (ata_pio_need_iordy(adev) && ((mode >> port_shift) & 0x03) == 0x00)
+		mode |= 0x01 << port_shift;
+	else if (((mode >> port_shift) & 0x03) == 0x01)
+		mode &= ~(0x03 << port_shift);
+	pci_write_config_byte(pdev, addr_mask, mode);
+
+	/*
+	 * Let's see if we need to enable IORDY checking on taskfile.
+	 *
+	 * NOTE: We can only disable IORDY if both drives agree to it.
+	 */
+	pci_read_config_word(pdev, tfaddr - 2, &reg);
 	if (ata_pio_need_iordy(adev))
-		reg |= 0x0200;		/* Enable IORDY */
-	pci_write_config_word(pdev, tfaddr-2, reg);
+		reg |=  0x0200;
+	else if (pair == NULL || !ata_pio_need_iordy(pair))
+		reg &= ~0x0200;
+	pci_write_config_word(pdev, tfaddr - 2, reg);
 }
 
 /**


[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux