diff options
| author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:54 -0400 |
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:54 -0400 |
| commit | 2f40c9b0b65b5635e2e13dfa068bd56fe7a8ff98 (patch) | |
| tree | f2ac83e1b59fb7cefde88455882817a2af99dbe4 | |
| parent | d45b70ab9bbf1a46ae52972d532f9e267b8d39d9 (diff) | |
ide: fix kmalloc() failure handling in ide_driveid_update()
* Doing kmalloc() in the middle of command execution is not only ugly
but leaves drive waiting to send data on kmalloc() failure. Fix it.
While at it:
* Unify error code paths.
* Fixup error message to be more useful and add missing KERN_ERR level.
* Rename 'stat' variable to 's'.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
| -rw-r--r-- | drivers/ide/ide-iops.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e0cfa2d2acc7..a955483d2404 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
| @@ -293,7 +293,12 @@ int ide_driveid_update(ide_drive_t *drive) | |||
| 293 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 293 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
| 294 | u16 *id; | 294 | u16 *id; |
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | u8 stat; | 296 | int rc; |
| 297 | u8 uninitialized_var(s); | ||
| 298 | |||
| 299 | id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); | ||
| 300 | if (id == NULL) | ||
| 301 | return 0; | ||
| 297 | 302 | ||
| 298 | /* | 303 | /* |
| 299 | * Re-read drive->id for possible DMA mode | 304 | * Re-read drive->id for possible DMA mode |
| @@ -306,25 +311,21 @@ int ide_driveid_update(ide_drive_t *drive) | |||
| 306 | tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); | 311 | tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); |
| 307 | 312 | ||
| 308 | if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { | 313 | if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { |
| 309 | SELECT_MASK(drive, 0); | 314 | rc = 1; |
| 310 | return 0; | 315 | goto out_err; |
| 311 | } | 316 | } |
| 312 | 317 | ||
| 313 | msleep(50); /* wait for IRQ and ATA_DRQ */ | 318 | msleep(50); /* wait for IRQ and ATA_DRQ */ |
| 314 | stat = tp_ops->read_status(hwif); | ||
| 315 | 319 | ||
| 316 | if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { | 320 | s = tp_ops->read_status(hwif); |
| 317 | SELECT_MASK(drive, 0); | 321 | |
| 318 | printk("%s: CHECK for good STATUS\n", drive->name); | 322 | if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { |
| 319 | return 0; | 323 | rc = 2; |
| 324 | goto out_err; | ||
| 320 | } | 325 | } |
| 326 | |||
| 321 | local_irq_save(flags); | 327 | local_irq_save(flags); |
| 322 | SELECT_MASK(drive, 0); | 328 | SELECT_MASK(drive, 0); |
| 323 | id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); | ||
| 324 | if (!id) { | ||
| 325 | local_irq_restore(flags); | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); | 329 | tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); |
| 329 | (void)tp_ops->read_status(hwif); /* clear drive IRQ */ | 330 | (void)tp_ops->read_status(hwif); /* clear drive IRQ */ |
| 330 | local_irq_enable(); | 331 | local_irq_enable(); |
| @@ -342,6 +343,12 @@ int ide_driveid_update(ide_drive_t *drive) | |||
| 342 | ide_dma_off(drive); | 343 | ide_dma_off(drive); |
| 343 | 344 | ||
| 344 | return 1; | 345 | return 1; |
| 346 | out_err: | ||
| 347 | SELECT_MASK(drive, 0); | ||
| 348 | if (rc == 2) | ||
| 349 | printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); | ||
| 350 | kfree(id); | ||
| 351 | return 0; | ||
| 345 | } | 352 | } |
| 346 | 353 | ||
| 347 | int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | 354 | int ide_config_drive_speed(ide_drive_t *drive, u8 speed) |
