提交 fe635c7e 编写于 作者: T Tejun Heo

[PATCH] libata: use preallocated buffers

It's not a very good idea to allocate memory during EH.  Use
statically allocated buffer for dev->id[] and add 512byte buffer
ap->sector_buf.  This buffer is owned by EH (or probing) and to be
used as temporary buffer for various purposes (IDENTIFY, NCQ log page
10h, PM GSCR block).
Signed-off-by: NTejun Heo <htejun@gmail.com>
上级 15869303
...@@ -1099,7 +1099,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) ...@@ -1099,7 +1099,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
* @dev: target device * @dev: target device
* @p_class: pointer to class of the target device (may be changed) * @p_class: pointer to class of the target device (may be changed)
* @post_reset: is this read ID post-reset? * @post_reset: is this read ID post-reset?
* @p_id: read IDENTIFY page (newly allocated) * @id: buffer to read IDENTIFY data into
* *
* Read ID data from the specified device. ATA_CMD_ID_ATA is * Read ID data from the specified device. ATA_CMD_ID_ATA is
* performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
...@@ -1113,12 +1113,11 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) ...@@ -1113,12 +1113,11 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
* 0 on success, -errno otherwise. * 0 on success, -errno otherwise.
*/ */
static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
unsigned int *p_class, int post_reset, u16 **p_id) unsigned int *p_class, int post_reset, u16 *id)
{ {
unsigned int class = *p_class; unsigned int class = *p_class;
struct ata_taskfile tf; struct ata_taskfile tf;
unsigned int err_mask = 0; unsigned int err_mask = 0;
u16 *id;
const char *reason; const char *reason;
int rc; int rc;
...@@ -1126,13 +1125,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ...@@ -1126,13 +1125,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
if (id == NULL) {
rc = -ENOMEM;
reason = "out of memory";
goto err_out;
}
retry: retry:
ata_tf_init(ap, &tf, dev->devno); ata_tf_init(ap, &tf, dev->devno);
...@@ -1194,13 +1186,12 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ...@@ -1194,13 +1186,12 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
} }
*p_class = class; *p_class = class;
*p_id = id;
return 0; return 0;
err_out: err_out:
printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
ap->id, dev->devno, reason); ap->id, dev->devno, reason);
kfree(id);
return rc; return rc;
} }
...@@ -1425,9 +1416,7 @@ static int ata_bus_probe(struct ata_port *ap) ...@@ -1425,9 +1416,7 @@ static int ata_bus_probe(struct ata_port *ap)
if (!ata_dev_enabled(dev)) if (!ata_dev_enabled(dev))
continue; continue;
kfree(dev->id); rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id);
dev->id = NULL;
rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id);
if (rc) if (rc)
goto fail; goto fail;
...@@ -2788,7 +2777,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, ...@@ -2788,7 +2777,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
int post_reset) int post_reset)
{ {
unsigned int class = dev->class; unsigned int class = dev->class;
u16 *id = NULL; u16 *id = (void *)ap->sector_buf;
int rc; int rc;
if (!ata_dev_enabled(dev)) { if (!ata_dev_enabled(dev)) {
...@@ -2796,8 +2785,8 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, ...@@ -2796,8 +2785,8 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
goto fail; goto fail;
} }
/* allocate & read ID data */ /* read ID data */
rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); rc = ata_dev_read_id(ap, dev, &class, post_reset, id);
if (rc) if (rc)
goto fail; goto fail;
...@@ -2807,8 +2796,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, ...@@ -2807,8 +2796,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
goto fail; goto fail;
} }
kfree(dev->id); memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
dev->id = id;
/* configure device according to the new ID */ /* configure device according to the new ID */
rc = ata_dev_configure(ap, dev, 0); rc = ata_dev_configure(ap, dev, 0);
...@@ -2818,7 +2806,6 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, ...@@ -2818,7 +2806,6 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
fail: fail:
printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n",
ap->id, dev->devno, rc); ap->id, dev->devno, rc);
kfree(id);
return rc; return rc;
} }
...@@ -4873,14 +4860,11 @@ void ata_host_set_remove(struct ata_host_set *host_set) ...@@ -4873,14 +4860,11 @@ void ata_host_set_remove(struct ata_host_set *host_set)
int ata_scsi_release(struct Scsi_Host *host) int ata_scsi_release(struct Scsi_Host *host)
{ {
struct ata_port *ap = ata_shost_to_port(host); struct ata_port *ap = ata_shost_to_port(host);
int i;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
ap->ops->port_disable(ap); ap->ops->port_disable(ap);
ata_host_remove(ap, 0); ata_host_remove(ap, 0);
for (i = 0; i < ATA_MAX_DEVICES; i++)
kfree(ap->device[i].id);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
return 1; return 1;
......
...@@ -360,7 +360,7 @@ struct ata_device { ...@@ -360,7 +360,7 @@ struct ata_device {
unsigned long flags; /* ATA_DFLAG_xxx */ unsigned long flags; /* ATA_DFLAG_xxx */
unsigned int class; /* ATA_DEV_xxx */ unsigned int class; /* ATA_DEV_xxx */
unsigned int devno; /* 0 or 1 */ unsigned int devno; /* 0 or 1 */
u16 *id; /* IDENTIFY xxx DEVICE data */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
u8 pio_mode; u8 pio_mode;
u8 dma_mode; u8 dma_mode;
u8 xfer_mode; u8 xfer_mode;
...@@ -425,6 +425,8 @@ struct ata_port { ...@@ -425,6 +425,8 @@ struct ata_port {
struct list_head eh_done_q; struct list_head eh_done_q;
void *private_data; void *private_data;
u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
}; };
struct ata_port_operations { struct ata_port_operations {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册