[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: Tejun Heo <htejun@gmail.com>
This commit is contained in:
@@ -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)
|
|||||||
* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user