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 /drivers/ide/ide-iops.c | |
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>
Diffstat (limited to 'drivers/ide/ide-iops.c')
-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) |