Re: [PATCH 2/6] pata_sis: Implement MWDMA for the UDMA 133 capable chips

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

 



On Monday 07 December 2009 02:26:00 pm Sergei Shtylyov wrote:
> Hello.
> 
> Alan Cox wrote:
> 
> > Bartlomiej pointed out that while this got fixed in the old driver whoever
> > did it didn't port it across.
> 
> > Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
> 
> [...]
> 
> > +static int mwdma_clip_to_pio(struct ata_device *adev)
> > +{
> > +	const int mwdma_to_pio[3] = {
> > +		XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
> > +	};
> > +	return min(mwdma_to_pio[adev->dma_mode - XFER_MW_DMA_0],
> > +				adev->pio_mode - XFER_PIO_0);
> > +}
> 
>     You call min() on uncomparables, i.e. mwdma_to_pio[] contains XFER_PIO_* 
> and adev->pio_mode - XFER_PIO_0 yields you a mode number. Thus the second 
> argument will always "win" as a minimal one.

There are more issues with the patch related to mwdma_clip_to_pio().

The function can return values between 0 and 4 which obviously won't work
well for the new code below for values > 2 (i.e. resulting in out-of-bounds
array access for the common-case of dev->pio_mode == 4).

@@ -400,21 +439,25 @@ static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
        int drive_pci = sis_old_port_base(adev);
-       u8 timing;
+       u16 timing;
 
-       const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
+       const u16 udma_bits[]  = {
+               0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100};
+       const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };
 
-       pci_read_config_byte(pdev, drive_pci + 1, &timing);
+       pci_read_config_word(pdev, drive_pci, &timing);
 
        if (adev->dma_mode < XFER_UDMA_0) {
-               /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
+               speed = mwdma_clip_to_pio(adev);
+               timing &= ~0x80FF;
+               timing |= mwdma_bits[speed];
        } else {
                /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
                speed = adev->dma_mode - XFER_UDMA_0;
-               timing &= ~0x8F;
+               timing &= ~0x8F00;
                timing |= udma_bits[speed];
        }
-       pci_write_config_byte(pdev, drive_pci + 1, timing);
+       pci_write_config_word(pdev, drive_pci, timing);
 }
 
 /**
@@ -434,21 +477,26 @@ static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *a
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
        int drive_pci = sis_old_port_base(adev);
-       u8 timing;
-       /* Low 4 bits are timing */
-       static const u8 udma_bits[]  = { 0x8F, 0x8A, 0x87, 0x85, 0x83, 0x82, 0x81};
+       u16 timing;
+       /* Bits 15-12  are timing */
+       static const u16 udma_bits[]  = {
+               0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100
+       };
+       static const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };
 
-       pci_read_config_byte(pdev, drive_pci + 1, &timing);
+       pci_read_config_word(pdev, drive_pci, &timing);
 
        if (adev->dma_mode < XFER_UDMA_0) {
-               /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
+               speed = mwdma_clip_to_pio(adev);
+               timing &= ~0x80FF;
+               timing = mwdma_bits[speed];
        } else {
                /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
                speed = adev->dma_mode - XFER_UDMA_0;
-               timing &= ~0x8F;
+               timing &= ~0x8F00;
                timing |= udma_bits[speed];
        }
-       pci_write_config_byte(pdev, drive_pci + 1, timing);
+       pci_write_config_word(pdev, drive_pci, timing);
 }
 
 /**


--
Bartlomiej Zolnierkiewicz
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[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