From 5b90e990928919ae411a68b865e8a6ecac09a603 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:18 +0200 Subject: ide: cleanup ide_fix_driveid() Do all __le16_to_cpu() swapping in one loop. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 107 +++++++++---------------------------------------- 1 file changed, 20 insertions(+), 87 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 2cbadffe922e..68d655e0fa47 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -400,97 +400,30 @@ const struct ide_tp_ops default_tp_ops = { .output_data = ide_output_data, }; -void ide_fix_driveid (struct hd_driveid *id) +void ide_fix_driveid(struct hd_driveid *driveid) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN + u16 *id = (u16 *)driveid; int i; - u16 *stringcast; - - id->config = __le16_to_cpu(id->config); - id->cyls = __le16_to_cpu(id->cyls); - id->reserved2 = __le16_to_cpu(id->reserved2); - id->heads = __le16_to_cpu(id->heads); - id->track_bytes = __le16_to_cpu(id->track_bytes); - id->sector_bytes = __le16_to_cpu(id->sector_bytes); - id->sectors = __le16_to_cpu(id->sectors); - id->vendor0 = __le16_to_cpu(id->vendor0); - id->vendor1 = __le16_to_cpu(id->vendor1); - id->vendor2 = __le16_to_cpu(id->vendor2); - stringcast = (u16 *)&id->serial_no[0]; - for (i = 0; i < (20/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->buf_type = __le16_to_cpu(id->buf_type); - id->buf_size = __le16_to_cpu(id->buf_size); - id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); - stringcast = (u16 *)&id->fw_rev[0]; - for (i = 0; i < (8/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - stringcast = (u16 *)&id->model[0]; - for (i = 0; i < (40/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->dword_io = __le16_to_cpu(id->dword_io); - id->reserved50 = __le16_to_cpu(id->reserved50); - id->field_valid = __le16_to_cpu(id->field_valid); - id->cur_cyls = __le16_to_cpu(id->cur_cyls); - id->cur_heads = __le16_to_cpu(id->cur_heads); - id->cur_sectors = __le16_to_cpu(id->cur_sectors); - id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); - id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); - id->lba_capacity = __le32_to_cpu(id->lba_capacity); - id->dma_1word = __le16_to_cpu(id->dma_1word); - id->dma_mword = __le16_to_cpu(id->dma_mword); - id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); - id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); - id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); - id->eide_pio = __le16_to_cpu(id->eide_pio); - id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); - for (i = 0; i < 2; ++i) - id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); - for (i = 0; i < 4; ++i) - id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); - id->queue_depth = __le16_to_cpu(id->queue_depth); - for (i = 0; i < 4; ++i) - id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); - id->major_rev_num = __le16_to_cpu(id->major_rev_num); - id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); - id->command_set_1 = __le16_to_cpu(id->command_set_1); - id->command_set_2 = __le16_to_cpu(id->command_set_2); - id->cfsse = __le16_to_cpu(id->cfsse); - id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); - id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); - id->csf_default = __le16_to_cpu(id->csf_default); - id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->trseuc = __le16_to_cpu(id->trseuc); - id->trsEuc = __le16_to_cpu(id->trsEuc); - id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->mprc = __le16_to_cpu(id->mprc); - id->hw_config = __le16_to_cpu(id->hw_config); - id->acoustic = __le16_to_cpu(id->acoustic); - id->msrqs = __le16_to_cpu(id->msrqs); - id->sxfert = __le16_to_cpu(id->sxfert); - id->sal = __le16_to_cpu(id->sal); - id->spg = __le32_to_cpu(id->spg); - id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); - for (i = 0; i < 22; i++) - id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); - id->last_lun = __le16_to_cpu(id->last_lun); - id->word127 = __le16_to_cpu(id->word127); - id->dlf = __le16_to_cpu(id->dlf); - id->csfo = __le16_to_cpu(id->csfo); - for (i = 0; i < 26; i++) - id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); - id->word156 = __le16_to_cpu(id->word156); - for (i = 0; i < 3; i++) - id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); - id->cfa_power = __le16_to_cpu(id->cfa_power); - for (i = 0; i < 15; i++) - id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); - for (i = 0; i < 30; i++) - id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); - for (i = 0; i < 49; i++) - id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); - id->integrity_word = __le16_to_cpu(id->integrity_word); + + for (i = 0; i < 256; i++) { + /* these words are accessed as two 8-bit values */ + if (i == 47 || i == 49 || i == 51 || i == 52 || i == 59) + continue; + if (i == 60 || i == 61) /* ->lba_capacity is 32-bit */ + continue; + if (i == 98 || i == 99) /* ->spg is 32-bit */ + continue; + if (i > 99 && i < 104) /* ->lba_capacity_2 is 64-bit */ + continue; + + id[i] = __le16_to_cpu(id[i]); + } + + driveid->lba_capacity = __le32_to_cpu(driveid->lba_capacity); + driveid->spg = __le32_to_cpu(driveid->spg); + driveid->lba_capacity_2 = __le64_to_cpu(driveid->lba_capacity_2); # else # error "Please fix " # endif -- cgit v1.2.3 From 4dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5ab Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:19 +0200 Subject: ide: make drive->id an union (take 2) Make drive->id an unnamed union so id can be accessed either by using 'u16 *id' or 'struct hd_driveid *driveid'. Then convert all existing drive->id users accordingly (using 'u16 *id' when possible). This is an intermediate step to make ide 'struct hd_driveid'-free. While at it: - Add missing KERN_CONTs in it821x.c. - Use ATA_ID_WORDS and ATA_ID_*_LEN defines. - Remove unnecessary checks for drive->id. - s/drive_table/table/ in ide_in_drive_list(). - Cleanup ide_config_drive_speed() a bit. - s/drive1/dev1/ & s/drive0/dev0/ in ide_undecoded_slave(). v2: Fix typo in drivers/ide/ppc/pmac.c. (From Stephen Rothwell) There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 80 ++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 42 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 68d655e0fa47..01b1943b315e 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -400,11 +400,11 @@ const struct ide_tp_ops default_tp_ops = { .output_data = ide_output_data, }; -void ide_fix_driveid(struct hd_driveid *driveid) +void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN - u16 *id = (u16 *)driveid; + struct hd_driveid *driveid = (struct hd_driveid *)id; int i; for (i = 0; i < 256; i++) { @@ -593,18 +593,18 @@ EXPORT_SYMBOL(ide_wait_stat); /** * ide_in_drive_list - look for drive in black/white list * @id: drive identifier - * @drive_table: list to inspect + * @table: list to inspect * * Look for a drive in the blacklist and the whitelist tables * Returns 1 if the drive is found in the table. */ -int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) +int ide_in_drive_list(u16 *id, const struct drive_list_entry *table) { - for ( ; drive_table->id_model; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - (!drive_table->id_firmware || - strstr(id->fw_rev, drive_table->id_firmware))) + for ( ; table->id_model; table++) + if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) && + (!table->id_firmware || + strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware))) return 1; return 0; } @@ -635,7 +635,7 @@ static const struct drive_list_entry ivb_list[] = { u8 eighty_ninty_three (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; int ivb = ide_in_drive_list(id, ivb_list); if (hwif->cbl == ATA_CBL_PATA40_SHORT) @@ -657,7 +657,8 @@ u8 eighty_ninty_three (ide_drive_t *drive) * - force bit13 (80c cable present) check also for !ivb devices * (unless the slave device is pre-ATA3) */ - if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000))) + if ((id[ATA_ID_HW_CONFIG] & 0x4000) || + (ivb && (id[ATA_ID_HW_CONFIG] & 0x2000))) return 1; no_80w: @@ -678,7 +679,7 @@ int ide_driveid_update(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; - struct hd_driveid *id; + u16 *id; unsigned long timeout, flags; u8 stat; @@ -722,16 +723,16 @@ int ide_driveid_update(ide_drive_t *drive) local_irq_enable(); local_irq_restore(flags); ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - - if (drive->using_dma && ide_id_dma_bug(drive)) - ide_dma_off(drive); - } + + drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; + drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; + drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; + /* anything more ? */ + + kfree(id); + + if (drive->using_dma && ide_id_dma_bug(drive)) + ide_dma_off(drive); return 1; } @@ -740,6 +741,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; + u16 *id = drive->id, i; int error = 0; u8 stat; ide_task_t task; @@ -750,7 +752,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ - if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) + if ((speed & 0xf8) == XFER_PIO_0 && !(drive->driveid->capability & 8)) goto skip; /* @@ -802,9 +804,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) return error; } - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; + id[ATA_ID_UDMA_MODES] &= ~0xFF00; + id[ATA_ID_MWDMA_MODES] &= ~0x0F00; + id[ATA_ID_SWDMA_MODES] &= ~0x0F00; skip: #ifdef CONFIG_BLK_DEV_IDEDMA @@ -814,23 +816,17 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ide_dma_off_quietly(drive); #endif - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; + if (speed >= XFER_UDMA_0) { + i = 1 << (speed - XFER_UDMA_0); + id[ATA_ID_UDMA_MODES] |= (i << 8 | i); + } else if (speed >= XFER_MW_DMA_0) { + i = 1 << (speed - XFER_MW_DMA_0); + id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); + } else if (speed >= XFER_SW_DMA_0) { + i = 1 << (speed - XFER_SW_DMA_0); + id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); } + if (!drive->init_speed) drive->init_speed = speed; drive->current_speed = speed; @@ -1035,7 +1031,7 @@ out: static void ide_disk_pre_reset(ide_drive_t *drive) { - int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; + int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; drive->special.all = 0; drive->special.b.set_geometry = legacy; -- cgit v1.2.3 From 48fb2688aa67baba373531cc4ed2d9e695983c3f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:19 +0200 Subject: ide: remove drive->driveid * Factor out HDIO_[OBSOLETE,GET]_IDENTITY ioctls handling to ide_get_identity_ioctl(). * Use temporary buffer in ide_get_identity_ioctl() instead of accessing drive->id directly. * Add ide_id_to_hd_driveid() inline to convert raw id into struct hd_driveid format (needed on big-endian). * Use ide_id_to_hd_driveid() in ide_get_identity_ioctl(), cleanup ide_fix_driveid() and switch ide to use use raw id. * Remove no longer needed drive->driveid. This leaves us with 3 users of struct hd_driveid in tree: - arch/um/drivers/ubd_kern.c - drivers/block/xsysace.c - drivers/usb/storage/isd200.c While at it: * Use ata_id_u{32,64}() and ata_id_has_{dma,lba,iordy}() macros. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 01b1943b315e..95495e4219ff 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -404,26 +404,10 @@ void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN - struct hd_driveid *driveid = (struct hd_driveid *)id; int i; - for (i = 0; i < 256; i++) { - /* these words are accessed as two 8-bit values */ - if (i == 47 || i == 49 || i == 51 || i == 52 || i == 59) - continue; - if (i == 60 || i == 61) /* ->lba_capacity is 32-bit */ - continue; - if (i == 98 || i == 99) /* ->spg is 32-bit */ - continue; - if (i > 99 && i < 104) /* ->lba_capacity_2 is 64-bit */ - continue; - + for (i = 0; i < 256; i++) id[i] = __le16_to_cpu(id[i]); - } - - driveid->lba_capacity = __le32_to_cpu(driveid->lba_capacity); - driveid->spg = __le32_to_cpu(driveid->spg); - driveid->lba_capacity_2 = __le64_to_cpu(driveid->lba_capacity_2); # else # error "Please fix " # endif @@ -752,7 +736,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ - if ((speed & 0xf8) == XFER_PIO_0 && !(drive->driveid->capability & 8)) + if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0) goto skip; /* -- cgit v1.2.3 From aaaade3f059fa1b57283d4a7c8351a42ec747bf0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:21 +0200 Subject: ide: WIN_* -> ATA_CMD_* * Use ATA_CMD_* defines instead of WIN_* ones. While at it: * EXABYTE_ENABLE_NEXT -> ATA_EXABYTE_ENABLE_NEST * SETFEATURES_{EN,DIS}_WCACHE -> SETFEATURES_WC_{ON,OFF} * SETFEATURES_{EN,DIS}_AAM -> SETFEATURES_AAM_{ON,OFF} * SMART_* -> ATA_SMART_* * Remove stale comment from ide-proc.c. Partially based on earlier work by Chris Wedgwood. Acked-by: Chris Wedgwood Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 95495e4219ff..21647a2eaff9 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -418,7 +418,7 @@ void ide_fix_driveid(u16 *id) * ide_fixstring() cleans up and (optionally) byte-swaps a text string, * removing leading/trailing blanks and compressing internal blanks. * It is primarily used to tidy up the model name/number fields as - * returned by the WIN_[P]IDENTIFY commands. + * returned by the ATA_CMD_ID_ATA[PI] commands. */ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) @@ -675,7 +675,7 @@ int ide_driveid_update(ide_drive_t *drive) SELECT_MASK(drive, 1); tp_ops->set_irq(hwif, 0); msleep(50); - tp_ops->exec_command(hwif, WIN_IDENTIFY); + tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); timeout = jiffies + WAIT_WORSTCASE; do { if (time_after(jiffies, timeout)) { @@ -770,7 +770,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) tp_ops->tf_load(drive, &task); - tp_ops->exec_command(hwif, WIN_SETFEATURES); + tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); if (drive->quirk_list == 2) tp_ops->set_irq(hwif, 1); @@ -890,7 +890,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD); + hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); ndelay(400); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1100,7 +1100,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) pre_reset(drive); SELECT_DRIVE(drive); udelay (20); - tp_ops->exec_command(hwif, WIN_SRST); + tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); ndelay(400); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; -- cgit v1.2.3 From 3a7d24841ad794ae64c90d7d00d62a83741912aa Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:21 +0200 Subject: ide: use ATA_* defines instead of *_STAT and *_ERR ones * ERR_STAT -> ATA_ERR * INDEX_STAT -> ATA_IDX * ECC_STAT -> ATA_CORR * DRQ_STAT -> ATA_DRQ * SEEK_STAT -> ATA_DSC * WRERR_STAT -> ATA_DF * READY_STAT -> ATA_DRDY * BUSY_STAT -> ATA_BUSY * MARK_ERR -> ATA_AMNF * TRK0_ERR -> ATA_TRK0NF * ABRT_ERR -> ATA_ABORTED * MCR_ERR -> ATA_MCR * ID_ERR -> ATA_IDNF * MC_ERR -> ATA_MC * ECC_ERR -> ATA_UNC * ICRC_ERR -> ATA_ICRC * BBD_ERR -> ATA_BBK Also: * ILI_ERR -> ATAPI_ILI * EOM_ERR -> ATAPI_EOM * LFS_ERR -> ATAPI_LFS * CD -> ATAPI_COD * IO -> ATAPI_IO Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 21647a2eaff9..8cfa6125c7a4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -473,7 +473,7 @@ int drive_is_ready (ide_drive_t *drive) /* Note: this may clear a pending IRQ!! */ stat = hwif->tp_ops->read_status(hwif); - if (stat & BUSY_STAT) + if (stat & ATA_BUSY) /* drive busy: definitely not interrupting */ return 0; @@ -505,10 +505,10 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti udelay(1); /* spec allows drive 400ns to assert "BUSY" */ stat = tp_ops->read_status(hwif); - if (stat & BUSY_STAT) { + if (stat & ATA_BUSY) { local_irq_set(flags); timeout += jiffies; - while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) { + while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) { if (time_after(jiffies, timeout)) { /* * One last read after the timeout in case @@ -516,7 +516,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti * progress during the timeout.. */ stat = tp_ops->read_status(hwif); - if (!(stat & BUSY_STAT)) + if ((stat & ATA_BUSY) == 0) break; local_irq_restore(flags); @@ -685,12 +685,12 @@ int ide_driveid_update(ide_drive_t *drive) msleep(50); /* give drive a breather */ stat = tp_ops->read_altstatus(hwif); - } while (stat & BUSY_STAT); + } while (stat & ATA_BUSY); - msleep(50); /* wait for IRQ and DRQ_STAT */ + msleep(50); /* wait for IRQ and ATA_DRQ */ stat = tp_ops->read_status(hwif); - if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { + if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { SELECT_MASK(drive, 0); printk("%s: CHECK for good STATUS\n", drive->name); return 0; @@ -776,7 +776,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) tp_ops->set_irq(hwif, 1); error = __ide_wait_stat(drive, drive->ready_stat, - BUSY_STAT|DRQ_STAT|ERR_STAT, + ATA_BUSY | ATA_DRQ | ATA_ERR, WAIT_CMD, &stat); SELECT_MASK(drive, 0); @@ -923,7 +923,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) udelay (10); stat = hwif->tp_ops->read_status(hwif); - if (OK_STAT(stat, 0, BUSY_STAT)) + if (OK_STAT(stat, 0, ATA_BUSY)) printk("%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwgroup->poll_timeout)) { @@ -969,7 +969,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) tmp = hwif->tp_ops->read_status(hwif); - if (!OK_STAT(tmp, 0, BUSY_STAT)) { + if (!OK_STAT(tmp, 0, ATA_BUSY)) { if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); /* continue polling */ @@ -1183,7 +1183,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) */ mdelay(1); stat = hwif->tp_ops->read_status(hwif); - if ((stat & BUSY_STAT) == 0) + if ((stat & ATA_BUSY) == 0) return 0; /* * Assume a value of 0xff means nothing is connected to -- cgit v1.2.3 From 1a7809e3499921a016d203b9ee51a77d3cc1dc98 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 10 Oct 2008 22:39:22 +0200 Subject: ide: re-code ide_fixstring() loop to be less evil On Friday 25 July 2008, Linus Torvalds wrote: > > On Fri, 25 Jul 2008, Ben Dooks wrote: > > > > personally, i would much prefer to see the loop being less evil > > like: > > > > for (p = s; p < end; p += 2) > > be16_to_cpus((u16 *)p); > > Well, in this case, the code actually depends on 'p' being back at the > start of the buffer by the end of it all, so it would need some more > changes than that. > > But yes, I applied David's patch, but I _also_ suspect that we would be > better off without code that does horrid things like casts and assignments > inside the function arguments. > > So it would be nice to re-code that loop to be more readable. But due to > the reliance of 'p' being 's' after the loop, the minimal patch would be > something like the appended. > > Bartlomiej - take this or not, I'm not going to commit it - I haven't > tested it, nor do I even have any machines that would trigger it. So this > is more a "maybe something like this" than anything else. From: Linus Torvalds CC: Ben Dooks Cc: David Miller Cc: harvey.harrison@gmail.com Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 8cfa6125c7a4..004803030f64 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -423,14 +423,16 @@ void ide_fix_driveid(u16 *id) void ide_fixstring (u8 *s, const int bytecount, const int byteswap) { - u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ + u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */ if (byteswap) { /* convert from big-endian to host byte order */ - for (p = end ; p != s;) - be16_to_cpus((u16 *)(p -= 2)); + for (p = s ; p != end ; p += 2) + be16_to_cpus((u16 *) p); } + /* strip leading blanks */ + p = s; while (s != end && *s == ' ') ++s; /* compress internal blanks and strip trailing blanks */ -- cgit v1.2.3 From b163f46d5ecf48d883ce156e5e5a21a1a9a125c7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:23 +0200 Subject: ide: enhance ide_busy_sleep() * Make ide_busy_sleep() take timeout value as a parameter and also allow use of AltStatus Register if requested with altstatus parameter. Update existing users accordingly. * Convert ide_driveid_update() and actual_try_to_identify() to use ide_busy_sleep(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 004803030f64..a940d127aae3 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -666,7 +666,7 @@ int ide_driveid_update(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; - unsigned long timeout, flags; + unsigned long flags; u8 stat; /* @@ -678,16 +678,11 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->set_irq(hwif, 0); msleep(50); tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - SELECT_MASK(drive, 0); - return 0; /* drive timed-out */ - } - msleep(50); /* give drive a breather */ - stat = tp_ops->read_altstatus(hwif); - } while (stat & ATA_BUSY); + if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { + SELECT_MASK(drive, 0); + return 0; + } msleep(50); /* wait for IRQ and ATA_DRQ */ stat = tp_ops->read_status(hwif); -- cgit v1.2.3 From 3ceca727fe3a38dd8d7a3adf938fefda83eee8af Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:27 +0200 Subject: ide: include only when needed * Include directly in instead of through . * Include only when needed. Cc: Christoph Hellwig Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index a940d127aae3..ee44878e40d0 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 151a670186a0f8441798f90c8701647adb7a1589 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:28 +0200 Subject: ide: remove SECTOR_WORDS define Just use SECTOR_SIZE instead. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index ee44878e40d0..6256c2df62cc 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -693,7 +693,7 @@ int ide_driveid_update(ide_drive_t *drive) } local_irq_save(flags); SELECT_MASK(drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (!id) { local_irq_restore(flags); return 0; -- cgit v1.2.3 From 367d7e78dd48cf6ad35182a99d97abb5486e040e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:30 +0200 Subject: ide: ide_dev_is_sata() -> ata_id_is_sata() * Use optimized ATA version check from Sergei in ata_id_is_sata(). * ide_dev_is_sata() -> ata_id_is_sata() Cc: Jeff Garzik Cc: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 6256c2df62cc..0a2fd3b37ac4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -630,7 +630,7 @@ u8 eighty_ninty_three (ide_drive_t *drive) printk(KERN_DEBUG "%s: skipping word 93 validity check\n", drive->name); - if (ide_dev_is_sata(id) && !ivb) + if (ata_id_is_sata(id) && !ivb) return 1; if (hwif->cbl != ATA_CBL_PATA80 && !ivb) -- cgit v1.2.3 From 97100fc816badbbc162644cfde7ad39ae9211fb4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 13 Oct 2008 21:39:36 +0200 Subject: ide: add device flags Add 'unsigned long dev_flags' to ide_drive_t and convert bitfields to IDE_DFLAG_* flags. While at it: - IDE_DFLAG_ADDRESSING -> IDE_DFLAG_LBA48 - fixup some comments - remove needless g->flags zeroing from ide*_probe() There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 0a2fd3b37ac4..cec744cbbde0 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -647,7 +647,7 @@ u8 eighty_ninty_three (ide_drive_t *drive) return 1; no_80w: - if (drive->udma33_warned == 1) + if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED) return 0; printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, " @@ -655,7 +655,7 @@ no_80w: drive->name, hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host"); - drive->udma33_warned = 1; + drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED; return 0; } @@ -711,7 +711,7 @@ int ide_driveid_update(ide_drive_t *drive) kfree(id); - if (drive->using_dma && ide_id_dma_bug(drive)) + if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) ide_dma_off(drive); return 1; @@ -790,7 +790,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) skip: #ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0 && drive->using_dma) + if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA)) hwif->dma_ops->dma_host_set(drive, 1); else if (hwif->dma_ops) /* check if host supports DMA */ ide_dma_off_quietly(drive); @@ -1016,9 +1016,13 @@ static void ide_disk_pre_reset(ide_drive_t *drive) drive->special.all = 0; drive->special.b.set_geometry = legacy; drive->special.b.recalibrate = legacy; + drive->mult_count = 0; - if (!drive->keep_settings && !drive->using_dma) + + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && + (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) drive->mult_req = 0; + if (drive->mult_req != drive->mult_count) drive->special.b.set_multmode = 1; } @@ -1030,18 +1034,18 @@ static void pre_reset(ide_drive_t *drive) if (drive->media == ide_disk) ide_disk_pre_reset(drive); else - drive->post_reset = 1; + drive->dev_flags |= IDE_DFLAG_POST_RESET; - if (drive->using_dma) { + if (drive->dev_flags & IDE_DFLAG_USING_DMA) { if (drive->crc_count) ide_check_dma_crc(drive); else ide_dma_off(drive); } - if (!drive->keep_settings) { - if (!drive->using_dma) { - drive->unmask = 0; + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { + if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { + drive->dev_flags &= ~IDE_DFLAG_UNMASK; drive->io_32bit = 0; } return; -- cgit v1.2.3 From 7f612f272ad8abe82411f368bfacf793b466e1b3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 13 Oct 2008 21:39:40 +0200 Subject: ide: remove [ata_]select_t * Use 'drive->dn & 1' in ide_init_disk(). * remove [ata_]select_t. While at it: * Use ATA_DEVICE_OBS define in ide_port_init_devices_data(). Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cec744cbbde0..925fd037cdde 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -181,7 +181,7 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task) tf_outb(tf->lbah, io_ports->lbah_addr); if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - tf_outb((tf->device & HIHI) | drive->select.all, + tf_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); } EXPORT_SYMBOL_GPL(ide_tf_load); -- cgit v1.2.3 From 0e3d84a500d4e1672332b4961b98c35f6168e6f1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 13 Oct 2008 21:39:41 +0200 Subject: ide: factor out reset error reporting from reset_pollfunc() Factor out reset error reporting from reset_pollfunc() to ide_reset_report_error() helper. While at it: - fix KERN_* printk() levels - remove 'switch ()' Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 925fd037cdde..91182ebed468 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -940,6 +940,25 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) return ide_stopped; } +static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) +{ + static const char *err_master_vals[] = + { NULL, "passed", "formatter device error", + "sector buffer error", "ECC circuitry error", + "controlling MPU error" }; + + u8 err_master = err & 0x7f; + + printk(KERN_ERR "%s: reset: master: ", hwif->name); + if (err_master && err_master < 6) + printk(KERN_CONT "%s", err_master_vals[err_master]); + else + printk(KERN_CONT "error (0x%02x?)", err); + if (err & 0x80) + printk(KERN_CONT "; slave: failed"); + printk(KERN_CONT "\n"); +} + /* * reset_pollfunc() gets invoked to poll the interface for completion every 50ms * during an ide reset operation. If the drives have not yet responded, @@ -975,31 +994,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) drive->failures++; err = -EIO; } else { - printk("%s: reset: ", hwif->name); tmp = ide_read_error(drive); if (tmp == 1) { - printk("success\n"); + printk(KERN_INFO "%s: reset: success\n", hwif->name); drive->failures = 0; } else { + ide_reset_report_error(hwif, tmp); drive->failures++; - printk("master: "); - switch (tmp & 0x7f) { - case 1: printk("passed"); - break; - case 2: printk("formatter device error"); - break; - case 3: printk("sector buffer error"); - break; - case 4: printk("ECC circuitry error"); - break; - case 5: printk("controlling MPU error"); - break; - default:printk("error (0x%02x?)", tmp); - } - if (tmp & 0x80) - printk("; slave: failed"); - printk("\n"); err = -EIO; } } -- cgit v1.2.3 From 4abdc6ee7c47a1a6e12f95717e461baeebee5df7 Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Mon, 13 Oct 2008 21:39:50 +0200 Subject: ide: Implement disk shock protection support (v4) On user request (through sysfs), the IDLE IMMEDIATE command with UNLOAD FEATURE as specified in ATA-7 is issued to the device and processing of the request queue is stopped thereafter until the specified timeout expires or user space asks to resume normal operation. This is supposed to prevent the heads of a hard drive from accidentally crashing onto the platter when a heavy shock is anticipated (like a falling laptop expected to hit the floor). Port resets are deferred whenever a device on that port is in the parked state. v3: Elias Oltmanns wrote: [...] > >> 1. Make sure that no negative value is being passed to > >> jiffies_to_msecs() in ide_park_show(). > >> 2. Drop the superfluous variable hwif in ide_special_rq(). > >> 3. Skip initialisation of task and tf in ide_special_rq() if we are not > >> handling a (un)park request. > > > > Well, #3 should have been done differently because we donn't want to > > check for REQ_(UN)?PARK_HEADS more often than is necessary. > > While preparing the backport to 2.6.27, it has just occurred to me that > we need to clear the IDE_DFLAG_PARKED flag in ide_disk_pre_reset() > because this flag must not be set after *any* sort of access to the > device. v4: Fix a memory leak due to a missing blk_put_request() in issue_park_cmd(). Additionally, we should plug the queue when enqueueing the unpark request because there is no guarantee that the park timeout has not expired by then. Even though the chance for that to happen is very slim, the request might end up hanging in the queue until the next I/O operation is queued up. While at it, clean up the code a little: - make issue_park_cmd() a function of type void since nobody cares for the return value anyway; - use blk_start_queueing() instead of __blk_run_queue() since we don't have to worry about recursion; - remove a superfluous pointer deference in task_no_data_intr(). Signed-off-by: Elias Oltmanns Cc: Jeff Garzik , Cc: Randy Dunlap Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 91182ebed468..b762deb2dacb 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1020,6 +1020,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive) drive->special.b.recalibrate = legacy; drive->mult_count = 0; + drive->dev_flags &= ~IDE_DFLAG_PARKED; if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) @@ -1079,12 +1080,13 @@ static void pre_reset(ide_drive_t *drive) static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) { unsigned int unit; - unsigned long flags; + unsigned long flags, timeout; ide_hwif_t *hwif; ide_hwgroup_t *hwgroup; struct ide_io_ports *io_ports; const struct ide_tp_ops *tp_ops; const struct ide_port_ops *port_ops; + DEFINE_WAIT(wait); spin_lock_irqsave(&ide_lock, flags); hwif = HWIF(drive); @@ -1111,6 +1113,31 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) return ide_started; } + /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ + do { + unsigned long now; + + prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); + timeout = jiffies; + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *tdrive = &hwif->drives[unit]; + + if (tdrive->dev_flags & IDE_DFLAG_PRESENT && + tdrive->dev_flags & IDE_DFLAG_PARKED && + time_after(tdrive->sleep, timeout)) + timeout = tdrive->sleep; + } + + now = jiffies; + if (time_before_eq(timeout, now)) + break; + + spin_unlock_irqrestore(&ide_lock, flags); + timeout = schedule_timeout_uninterruptible(timeout - now); + spin_lock_irqsave(&ide_lock, flags); + } while (timeout); + finish_wait(&ide_park_wq, &wait); + /* * First, reset any device state data we were maintaining * for any of the drives on this interface. -- cgit v1.2.3 From e5403bff8a4018240f012fd4c7afa24c2e75b469 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 17 Oct 2008 18:09:15 +0200 Subject: ide: mask interrupt in ide_config_drive_speed() Apparently, there is no sense in unmasking IRQ on the controller when you call disable_irq_nosync() before doing this, set the nIEN bit afterwards, and then unmask IRQ again after the command completion, hence 0 passed to SELECT_MASK() before issuing the command in ide_config_drive_speed() is probably just a typo. Signed-off-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide/ide-iops.c') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b762deb2dacb..bb7a1ed8094e 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -755,7 +755,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) udelay(1); SELECT_DRIVE(drive); - SELECT_MASK(drive, 0); + SELECT_MASK(drive, 1); udelay(1); tp_ops->set_irq(hwif, 0); -- cgit v1.2.3