From b42fa133110fa952299fa76cbe91226c14838261 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Tue, 3 Jul 2007 22:28:34 +0200 Subject: [PATCH 1/8] ide: never called printk statement in ide-taskfile.c::wait_drive_not_busy Look at wait_drive_not_busy in drivers/ide/ide-taskfile.c: static u8 wait_drive_not_busy(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); int retries = 100; u8 stat; /* * Last sector was transfered, wait until drive is ready. * This can take up to 10 usec, but we will wait max 1 ms * (drive_cmd_intr() waits that long). */ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) udelay(10); if (!retries) printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); return stat; } `printk' is never called because `retries' never holds zero at the outside of `while' loop: when `retries' holds zero at the while's loop condition, `retries' will hold -1 at the if condition. Signed-off-by: Masatake YAMATO Cc: Chuck Ebbert Cc: joe@perches.com Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-taskfile.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 30175c7688e8..aa06dafb74ac 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -238,7 +238,7 @@ EXPORT_SYMBOL(task_no_data_intr); static u8 wait_drive_not_busy(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - int retries = 100; + int retries; u8 stat; /* @@ -246,10 +246,14 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) * This can take up to 10 usec, but we will wait max 1 ms * (drive_cmd_intr() waits that long). */ - while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) - udelay(10); + for (retries = 0; retries < 100; retries++) { + if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) + udelay(10); + else + break; + } - if (!retries) + if (stat & BUSY_STAT) printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); return stat; From 785955752fde4c555a1d9f74ddfe1f7aca3e0c7f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Jul 2007 22:28:35 +0200 Subject: [PATCH 2/8] ide: Fix a theoretical Ooops case Found by a static analyser. It is in theory possible we dereference dev->id when it has become invalid. Re-order to avoid this. Not needed for new-ide as we no longer support the crazy exabyte nest stuff Signed-off-by: Alan Cox Cc: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 41bfa4d21ab6..f5ce22c38f82 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -574,11 +574,11 @@ static inline u8 probe_for_drive (ide_drive_t *drive) /* look for ATAPI device */ (void) do_probe(drive, WIN_PIDENTIFY); } - if (strstr(drive->id->model, "E X A B Y T E N E S T")) - enable_nest(drive); if (!drive->present) /* drive not found */ return 0; + if (strstr(drive->id->model, "E X A B Y T E N E S T")) + enable_nest(drive); /* identification failed? */ if (!drive->id_read) { From 783353b1d3d1ed3ae4a0bd4ea4557bd4d77aa04e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 3 Jul 2007 22:28:35 +0200 Subject: [PATCH 3/8] hpt366: blacklist MAXTOR STM3320620A for UltraDMA/66 Add the MAXTOR STM3320620A drive into the UltraDMA/66 mode blacklist for the HPT36x chips. Signed-off-by: Sergei Shtylyov Acked-by: Linas Vepstas Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index ce8a5449a574..4f8017ac9900 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.04 Jun 4, 2007 + * linux/drivers/ide/pci/hpt366.c Version 1.05 Jun 26, 2007 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -182,6 +182,7 @@ static const char *bad_ata66_4[] = { "IC35L040AVER07-0", "IC35L060AVER07-0", "WDC AC310200R", + "MAXTOR STM3320620A", NULL }; From 96dcc08b0c6b730474469b10ed5eeda06e617deb Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 3 Jul 2007 22:28:35 +0200 Subject: [PATCH 4/8] hpt366: use correct enablebits for HPT36x The HPT36x chips finally turned out to have the channel enable bits -- however, badly implemented. Make use of them despite it's probably only going to burden the driver's code -- assuming both channels are always enabled by the HighPoint BIOS anyway... Signed-off-by: Sergei Shtylyov Acked-by: Linas Vepstas Cc: michal.kepien@poczta.onet.pl Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 4f8017ac9900..c33d0b0f11c9 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.05 Jun 26, 2007 + * linux/drivers/ide/pci/hpt366.c Version 1.06 Jun 27, 2007 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -1514,18 +1514,28 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) goto init_single; /* - * HPT36x chips are single channel and - * do not seem to have the channel enable bit... + * HPT36x chips have one channel per function and have + * both channel enable bits located differently and visible + * to both functions -- really stupid design decision... :-( + * Bit 4 is for the primary channel, bit 5 for the secondary. */ d->channels = 1; - d->enablebits[0].reg = 0; + d->enablebits[0].mask = d->enablebits[0].val = 0x10; if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { - u8 pin1 = 0, pin2 = 0; + u8 mcr1 = 0, pin1 = 0, pin2 = 0; int ret; pci_set_drvdata(dev2, info[rev]); + /* + * Now we'll have to force both channels enabled if + * at least one of them has been enabled by BIOS... + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x30) + pci_write_config_byte(dev, 0x50, mcr1 | 0x30); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); if (pin1 != pin2 && dev->irq == dev2->irq) { From 603a0e2c0a160ad8c2d00d71a700bb95482be5de Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 3 Jul 2007 22:28:35 +0200 Subject: [PATCH 5/8] amd74xx: resume fix * Driver can't skip programming transfer mode on the device in amd_set_drive() (similar fix has been applied to via82cxxx driver ages ago). * While at it remove redundant warning (ide_config_drive_speed() already produces more valuable one). * Bump driver version. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/amd74xx.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 9db1be826e80..a2be65fcf89c 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -1,5 +1,5 @@ /* - * Version 2.15 + * Version 2.16 * * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04 * IDE driver for Linux. @@ -244,10 +244,8 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed) struct ide_timing t, p; int T, UT; - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); + if (speed != XFER_PIO_SLOW) + ide_config_drive_speed(drive, speed); T = 1000000000 / amd_clock; UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2); From 52374f890c1d0d64148d55a20d995a0b3e0ae987 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 3 Jul 2007 22:28:35 +0200 Subject: [PATCH 6/8] it821x: fix incorrect SWDMA mask SWDMA modes are unsupported by it821x. Attempts to tune SWDMA modes always fail (due to sanity check in ->speedproc) and result in PIO being tuned. * Fix incorrect SWDMA mask so core code won't try these modes and will just tune PIO if no other DMA modes are available. * Bump driver version. Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Sergei Shtylyov --- drivers/ide/pci/it821x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 4bd4bf02e917..3aeb7f1b7916 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -1,6 +1,6 @@ /* - * linux/drivers/ide/pci/it821x.c Version 0.15 Jun 2 2007 + * linux/drivers/ide/pci/it821x.c Version 0.16 Jul 3 2007 * * Copyright (C) 2004 Red Hat * Copyright (C) 2007 Bartlomiej Zolnierkiewicz @@ -660,7 +660,6 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; hwif->ide_dma_check = &it821x_config_drive_for_dma; if (!(hwif->udma_four)) From 8006bf56e360a4db71d304df778870a371a9e930 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 3 Jul 2007 22:28:36 +0200 Subject: [PATCH 7/8] ide: pdc202xx_new PLL input clock fix Recently the PLL input clock of Promise 2027x is sometimes detected higher than expected (e.g. 20.027 MHz compared to 16.714 MHz). It seems sometimes the mdelay() function is not as precise as it used to be. Per Alan's advice, HT or power management might affect the precision of mdelay(). This patch calls gettimeofday() to measure the time elapsed and calculate the PLL input clock accordingly. Signed-off-by: Albert Lee Cc: Alan Cox Cc: Bahadir Balban Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/pdc202xx_new.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index cc0bfdcf1f19..0765dce6948e 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -306,11 +306,13 @@ static long __devinit read_counter(u32 dma_base) */ static long __devinit detect_pll_input_clock(unsigned long dma_base) { + struct timeval start_time, end_time; long start_count, end_count; - long pll_input; + long pll_input, usec_elapsed; u8 scr1; start_count = read_counter(dma_base); + do_gettimeofday(&start_time); /* Start the test mode */ outb(0x01, dma_base + 0x01); @@ -322,6 +324,7 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base) mdelay(10); end_count = read_counter(dma_base); + do_gettimeofday(&end_time); /* Stop the test mode */ outb(0x01, dma_base + 0x01); @@ -333,7 +336,10 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base) * Calculate the input clock in Hz * (the clock counter is 30 bit wide and counts down) */ - pll_input = ((start_count - end_count) & 0x3ffffff) * 100; + usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 + + (end_time.tv_usec - start_time.tv_usec); + pll_input = ((start_count - end_count) & 0x3ffffff) / 10 * + (10000000 / usec_elapsed); DBG("start[%ld] end[%ld]\n", start_count, end_count); From d61bcce9c1aa2c9f8a768d73c4c517f81d226725 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Jul 2007 22:28:36 +0200 Subject: [PATCH 8/8] ide: ide_scan_pcibus(): check __pci_register_driver return value drivers/ide/setup-pci.c: In function 'ide_scan_pcibus': drivers/ide/setup-pci.c:879: warning: ignoring return value of '__pci_register_driver', declared with attribute warn_unused_result Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/setup-pci.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 67035ba4bf5e..c88d33225cf9 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -872,11 +872,15 @@ void __init ide_scan_pcibus (int scan_direction) * are post init. */ - list_for_each_safe(l, n, &ide_pci_drivers) - { + list_for_each_safe(l, n, &ide_pci_drivers) { list_del(l); d = list_entry(l, struct pci_driver, node); - __pci_register_driver(d, d->driver.owner, d->driver.mod_name); + if (__pci_register_driver(d, d->driver.owner, + d->driver.mod_name)) { + printk(KERN_ERR "%s: failed to register driver " + "for %s\n", __FUNCTION__, + d->driver.mod_name); + } } } #endif