diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:35 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:35 -0400 |
commit | fe635c7e91036282e4fd0cc5b4eebc712e43270d (patch) | |
tree | 22054d039df52c19e729f30ceee836936a730ce6 | |
parent | 158693031d7c58a355ec1852052a4fca75fd3bda (diff) |
[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>
-rw-r--r-- | drivers/scsi/libata-core.c | 32 | ||||
-rw-r--r-- | include/linux/libata.h | 4 |
2 files changed, 11 insertions, 25 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 13bce43f1915..af55861a96e2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -1099,7 +1099,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) | |||
1099 | * @dev: target device | 1099 | * @dev: target device |
1100 | * @p_class: pointer to class of the target device (may be changed) | 1100 | * @p_class: pointer to class of the target device (may be changed) |
1101 | * @post_reset: is this read ID post-reset? | 1101 | * @post_reset: is this read ID post-reset? |
1102 | * @p_id: read IDENTIFY page (newly allocated) | 1102 | * @id: buffer to read IDENTIFY data into |
1103 | * | 1103 | * |
1104 | * Read ID data from the specified device. ATA_CMD_ID_ATA is | 1104 | * Read ID data from the specified device. ATA_CMD_ID_ATA is |
1105 | * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI | 1105 | * 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 | * 0 on success, -errno otherwise. | 1113 | * 0 on success, -errno otherwise. |
1114 | */ | 1114 | */ |
1115 | static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | 1115 | static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, |
1116 | unsigned int *p_class, int post_reset, u16 **p_id) | 1116 | unsigned int *p_class, int post_reset, u16 *id) |
1117 | { | 1117 | { |
1118 | unsigned int class = *p_class; | 1118 | unsigned int class = *p_class; |
1119 | struct ata_taskfile tf; | 1119 | struct ata_taskfile tf; |
1120 | unsigned int err_mask = 0; | 1120 | unsigned int err_mask = 0; |
1121 | u16 *id; | ||
1122 | const char *reason; | 1121 | const char *reason; |
1123 | int rc; | 1122 | int rc; |
1124 | 1123 | ||
@@ -1126,13 +1125,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1126 | 1125 | ||
1127 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ | 1126 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ |
1128 | 1127 | ||
1129 | id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); | ||
1130 | if (id == NULL) { | ||
1131 | rc = -ENOMEM; | ||
1132 | reason = "out of memory"; | ||
1133 | goto err_out; | ||
1134 | } | ||
1135 | |||
1136 | retry: | 1128 | retry: |
1137 | ata_tf_init(ap, &tf, dev->devno); | 1129 | ata_tf_init(ap, &tf, dev->devno); |
1138 | 1130 | ||
@@ -1194,13 +1186,12 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1194 | } | 1186 | } |
1195 | 1187 | ||
1196 | *p_class = class; | 1188 | *p_class = class; |
1197 | *p_id = id; | 1189 | |
1198 | return 0; | 1190 | return 0; |
1199 | 1191 | ||
1200 | err_out: | 1192 | err_out: |
1201 | printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", | 1193 | printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", |
1202 | ap->id, dev->devno, reason); | 1194 | ap->id, dev->devno, reason); |
1203 | kfree(id); | ||
1204 | return rc; | 1195 | return rc; |
1205 | } | 1196 | } |
1206 | 1197 | ||
@@ -1425,9 +1416,7 @@ static int ata_bus_probe(struct ata_port *ap) | |||
1425 | if (!ata_dev_enabled(dev)) | 1416 | if (!ata_dev_enabled(dev)) |
1426 | continue; | 1417 | continue; |
1427 | 1418 | ||
1428 | kfree(dev->id); | 1419 | rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); |
1429 | dev->id = NULL; | ||
1430 | rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); | ||
1431 | if (rc) | 1420 | if (rc) |
1432 | goto fail; | 1421 | goto fail; |
1433 | 1422 | ||
@@ -2788,7 +2777,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, | |||
2788 | int post_reset) | 2777 | int post_reset) |
2789 | { | 2778 | { |
2790 | unsigned int class = dev->class; | 2779 | unsigned int class = dev->class; |
2791 | u16 *id = NULL; | 2780 | u16 *id = (void *)ap->sector_buf; |
2792 | int rc; | 2781 | int rc; |
2793 | 2782 | ||
2794 | if (!ata_dev_enabled(dev)) { | 2783 | if (!ata_dev_enabled(dev)) { |
@@ -2796,8 +2785,8 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, | |||
2796 | goto fail; | 2785 | goto fail; |
2797 | } | 2786 | } |
2798 | 2787 | ||
2799 | /* allocate & read ID data */ | 2788 | /* read ID data */ |
2800 | rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); | 2789 | rc = ata_dev_read_id(ap, dev, &class, post_reset, id); |
2801 | if (rc) | 2790 | if (rc) |
2802 | goto fail; | 2791 | goto fail; |
2803 | 2792 | ||
@@ -2807,8 +2796,7 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, | |||
2807 | goto fail; | 2796 | goto fail; |
2808 | } | 2797 | } |
2809 | 2798 | ||
2810 | kfree(dev->id); | 2799 | memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); |
2811 | dev->id = id; | ||
2812 | 2800 | ||
2813 | /* configure device according to the new ID */ | 2801 | /* configure device according to the new ID */ |
2814 | rc = ata_dev_configure(ap, dev, 0); | 2802 | rc = ata_dev_configure(ap, dev, 0); |
@@ -2818,7 +2806,6 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, | |||
2818 | fail: | 2806 | fail: |
2819 | printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", | 2807 | printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", |
2820 | ap->id, dev->devno, rc); | 2808 | ap->id, dev->devno, rc); |
2821 | kfree(id); | ||
2822 | return rc; | 2809 | return rc; |
2823 | } | 2810 | } |
2824 | 2811 | ||
@@ -4873,14 +4860,11 @@ void ata_host_set_remove(struct ata_host_set *host_set) | |||
4873 | int ata_scsi_release(struct Scsi_Host *host) | 4860 | int ata_scsi_release(struct Scsi_Host *host) |
4874 | { | 4861 | { |
4875 | struct ata_port *ap = ata_shost_to_port(host); | 4862 | struct ata_port *ap = ata_shost_to_port(host); |
4876 | int i; | ||
4877 | 4863 | ||
4878 | DPRINTK("ENTER\n"); | 4864 | DPRINTK("ENTER\n"); |
4879 | 4865 | ||
4880 | ap->ops->port_disable(ap); | 4866 | ap->ops->port_disable(ap); |
4881 | ata_host_remove(ap, 0); | 4867 | ata_host_remove(ap, 0); |
4882 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
4883 | kfree(ap->device[i].id); | ||
4884 | 4868 | ||
4885 | DPRINTK("EXIT\n"); | 4869 | DPRINTK("EXIT\n"); |
4886 | return 1; | 4870 | return 1; |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 220b9d7bfc28..0e1a3be39475 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -360,7 +360,7 @@ struct ata_device { | |||
360 | unsigned long flags; /* ATA_DFLAG_xxx */ | 360 | unsigned long flags; /* ATA_DFLAG_xxx */ |
361 | unsigned int class; /* ATA_DEV_xxx */ | 361 | unsigned int class; /* ATA_DEV_xxx */ |
362 | unsigned int devno; /* 0 or 1 */ | 362 | unsigned int devno; /* 0 or 1 */ |
363 | u16 *id; /* IDENTIFY xxx DEVICE data */ | 363 | u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ |
364 | u8 pio_mode; | 364 | u8 pio_mode; |
365 | u8 dma_mode; | 365 | u8 dma_mode; |
366 | u8 xfer_mode; | 366 | u8 xfer_mode; |
@@ -425,6 +425,8 @@ struct ata_port { | |||
425 | struct list_head eh_done_q; | 425 | struct list_head eh_done_q; |
426 | 426 | ||
427 | void *private_data; | 427 | void *private_data; |
428 | |||
429 | u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */ | ||
428 | }; | 430 | }; |
429 | 431 | ||
430 | struct ata_port_operations { | 432 | struct ata_port_operations { |