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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent d45b70ab
...@@ -293,7 +293,12 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -293,7 +293,12 @@ int ide_driveid_update(ide_drive_t *drive)
const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u16 *id; u16 *id;
unsigned long flags; unsigned long flags;
u8 stat; int rc;
u8 uninitialized_var(s);
id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
if (id == NULL)
return 0;
/* /*
* Re-read drive->id for possible DMA mode * Re-read drive->id for possible DMA mode
...@@ -306,25 +311,21 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -306,25 +311,21 @@ int ide_driveid_update(ide_drive_t *drive)
tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
SELECT_MASK(drive, 0); rc = 1;
return 0; goto out_err;
} }
msleep(50); /* wait for IRQ and ATA_DRQ */ msleep(50); /* wait for IRQ and ATA_DRQ */
stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { s = tp_ops->read_status(hwif);
SELECT_MASK(drive, 0);
printk("%s: CHECK for good STATUS\n", drive->name); if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
return 0; rc = 2;
goto out_err;
} }
local_irq_save(flags); local_irq_save(flags);
SELECT_MASK(drive, 0); SELECT_MASK(drive, 0);
id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
if (!id) {
local_irq_restore(flags);
return 0;
}
tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
(void)tp_ops->read_status(hwif); /* clear drive IRQ */ (void)tp_ops->read_status(hwif); /* clear drive IRQ */
local_irq_enable(); local_irq_enable();
...@@ -342,6 +343,12 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -342,6 +343,12 @@ int ide_driveid_update(ide_drive_t *drive)
ide_dma_off(drive); ide_dma_off(drive);
return 1; return 1;
out_err:
SELECT_MASK(drive, 0);
if (rc == 2)
printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__);
kfree(id);
return 0;
} }
int ide_config_drive_speed(ide_drive_t *drive, u8 speed) int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment