aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
commit8185d5aa93e0a5c111adc4952a5b87193a68ae5b (patch)
tree431aeb09a448b7b07a353e12f4fe931ebb8555cd /drivers/ide
parent263138a0ad6e38de7f6526b7de037ed4511308ef (diff)
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros. * Add 'const struct ide_devset **settings' to ide_driver_t. * Use 'const struct ide_devset **settings' in ide_drive_t instead of 'struct ide_settings_s *settings'. Then convert core code and device drivers to use struct ide_devset and co.: - device settings are no longer allocated dynamically for each device but instead there is an unique struct ide_devset instance per setting - device driver keeps the pointer to the table of pointers to its settings in ide_driver_t.settings - generic settings are kept in ide_generic_setting[] - ide_proc_[un]register_driver(), ide_find_setting_by_name(), ide_{read,write}_setting() and proc_ide_{read,write}_settings() are updated accordingly - ide*_add_settings() are removed * Remove no longer used __ide_add_setting(), ide_add_setting(), __ide_remove_setting() and auto_remove_settings(). * Remove no longer used TYPE_*, SETTING_*, ide_procset_t and ide_settings_t. * ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap, ->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields can now be bitfield flags. While at it: * Rename ide_find_setting_by_name() to ide_find_setting(). * Rename write_wcache() to set_wcache(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/ide-cd.c15
-rw-r--r--drivers/ide/ide-disk.c87
-rw-r--r--drivers/ide/ide-floppy.c35
-rw-r--r--drivers/ide/ide-probe.c2
-rw-r--r--drivers/ide/ide-proc.c279
-rw-r--r--drivers/ide/ide-tape.c74
-rw-r--r--drivers/ide/ide.c21
7 files changed, 230 insertions, 283 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 34a1aeaa15dd..1f5652326489 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1809,13 +1809,12 @@ static ide_proc_entry_t idecd_proc[] = {
1809 { NULL, 0, NULL, NULL } 1809 { NULL, 0, NULL, NULL }
1810}; 1810};
1811 1811
1812static void ide_cdrom_add_settings(ide_drive_t *drive) 1812ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
1813{ 1813
1814 ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 1814static const struct ide_devset *idecd_settings[] = {
1815 &drive->dsc_overlap, NULL); 1815 &ide_devset_dsc_overlap,
1816} 1816 NULL
1817#else 1817};
1818static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
1819#endif 1818#endif
1820 1819
1821static const struct cd_list_entry ide_cd_quirks_list[] = { 1820static const struct cd_list_entry ide_cd_quirks_list[] = {
@@ -1926,7 +1925,6 @@ static int ide_cdrom_setup(ide_drive_t *drive)
1926 } 1925 }
1927 1926
1928 ide_proc_register_driver(drive, cd->driver); 1927 ide_proc_register_driver(drive, cd->driver);
1929 ide_cdrom_add_settings(drive);
1930 return 0; 1928 return 0;
1931} 1929}
1932 1930
@@ -1977,6 +1975,7 @@ static ide_driver_t ide_cdrom_driver = {
1977 .error = __ide_error, 1975 .error = __ide_error,
1978#ifdef CONFIG_IDE_PROC_FS 1976#ifdef CONFIG_IDE_PROC_FS
1979 .proc = idecd_proc, 1977 .proc = idecd_proc,
1978 .settings = idecd_settings,
1980#endif 1979#endif
1981}; 1980};
1982 1981
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7a15907dce1d..2e43ae15fb1b 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -599,6 +599,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
599 rq->special = task; 599 rq->special = task;
600} 600}
601 601
602ide_devset_get(multcount, mult_count);
603
602/* 604/*
603 * This is tightly woven into the driver->do_special can not touch. 605 * This is tightly woven into the driver->do_special can not touch.
604 * DON'T do it again until a total personality rewrite is committed. 606 * DON'T do it again until a total personality rewrite is committed.
@@ -625,6 +627,8 @@ static int set_multcount(ide_drive_t *drive, int arg)
625 return (drive->mult_count == arg) ? 0 : -EIO; 627 return (drive->mult_count == arg) ? 0 : -EIO;
626} 628}
627 629
630ide_devset_get(nowerr, nowerr);
631
628static int set_nowerr(ide_drive_t *drive, int arg) 632static int set_nowerr(ide_drive_t *drive, int arg)
629{ 633{
630 if (arg < 0 || arg > 1) 634 if (arg < 0 || arg > 1)
@@ -673,7 +677,9 @@ static void update_ordered(ide_drive_t *drive)
673 blk_queue_ordered(drive->queue, ordered, prep_fn); 677 blk_queue_ordered(drive->queue, ordered, prep_fn);
674} 678}
675 679
676static int write_cache(ide_drive_t *drive, int arg) 680ide_devset_get(wcache, wcache);
681
682static int set_wcache(ide_drive_t *drive, int arg)
677{ 683{
678 ide_task_t args; 684 ide_task_t args;
679 int err = 1; 685 int err = 1;
@@ -710,6 +716,8 @@ static int do_idedisk_flushcache(ide_drive_t *drive)
710 return ide_no_data_taskfile(drive, &args); 716 return ide_no_data_taskfile(drive, &args);
711} 717}
712 718
719ide_devset_get(acoustic, acoustic);
720
713static int set_acoustic(ide_drive_t *drive, int arg) 721static int set_acoustic(ide_drive_t *drive, int arg)
714{ 722{
715 ide_task_t args; 723 ide_task_t args;
@@ -727,6 +735,8 @@ static int set_acoustic(ide_drive_t *drive, int arg)
727 return 0; 735 return 0;
728} 736}
729 737
738ide_devset_get(lba_addressing, addressing);
739
730/* 740/*
731 * drive->addressing: 741 * drive->addressing:
732 * 0: 28-bit 742 * 0: 28-bit
@@ -750,33 +760,33 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
750} 760}
751 761
752#ifdef CONFIG_IDE_PROC_FS 762#ifdef CONFIG_IDE_PROC_FS
753static void idedisk_add_settings(ide_drive_t *drive) 763ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
754{ 764ide_devset_rw_nolock(address, 0, 2, lba_addressing);
755 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, 765ide_devset_rw_nolock(multcount, 0, 16, multcount);
756 &drive->bios_cyl, NULL); 766ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
757 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, 767ide_devset_rw_nolock(wcache, 0, 1, wcache);
758 &drive->bios_head, NULL); 768
759 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, 769ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
760 &drive->bios_sect, NULL); 770ide_devset_rw(bios_head, 0, 255, bios_head);
761 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, 771ide_devset_rw(bios_sect, 0, 63, bios_sect);
762 &drive->addressing, set_lba_addressing); 772ide_devset_rw(failures, 0, 65535, failures);
763 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, 16, 1, 1, 773ide_devset_rw(lun, 0, 7, lun);
764 &drive->mult_count, set_multcount); 774ide_devset_rw(max_failures, 0, 65535, max_failures);
765 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 775
766 &drive->nowerr, set_nowerr); 776static const struct ide_devset *idedisk_settings[] = {
767 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, 777 &ide_devset_acoustic,
768 &drive->lun, NULL); 778 &ide_devset_address,
769 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 779 &ide_devset_bios_cyl,
770 &drive->wcache, write_cache); 780 &ide_devset_bios_head,
771 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, 781 &ide_devset_bios_sect,
772 &drive->acoustic, set_acoustic); 782 &ide_devset_failures,
773 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, 783 &ide_devset_lun,
774 &drive->failures, NULL); 784 &ide_devset_max_failures,
775 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 785 &ide_devset_multcount,
776 1, 1, &drive->max_failures, NULL); 786 &ide_devset_nowerr,
777} 787 &ide_devset_wcache,
778#else 788 NULL
779static inline void idedisk_add_settings(ide_drive_t *drive) { ; } 789};
780#endif 790#endif
781 791
782static void idedisk_setup(ide_drive_t *drive) 792static void idedisk_setup(ide_drive_t *drive)
@@ -788,7 +798,6 @@ static void idedisk_setup(ide_drive_t *drive)
788 unsigned long long capacity; 798 unsigned long long capacity;
789 799
790 ide_proc_register_driver(drive, idkp->driver); 800 ide_proc_register_driver(drive, idkp->driver);
791 idedisk_add_settings(drive);
792 801
793 if (drive->id_read == 0) 802 if (drive->id_read == 0)
794 return; 803 return;
@@ -880,7 +889,7 @@ static void idedisk_setup(ide_drive_t *drive)
880 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) 889 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
881 drive->wcache = 1; 890 drive->wcache = 1;
882 891
883 write_cache(drive, 1); 892 set_wcache(drive, 1);
884} 893}
885 894
886static void ide_cacheflush_p(ide_drive_t *drive) 895static void ide_cacheflush_p(ide_drive_t *drive)
@@ -976,6 +985,7 @@ static ide_driver_t idedisk_driver = {
976 .error = __ide_error, 985 .error = __ide_error,
977#ifdef CONFIG_IDE_PROC_FS 986#ifdef CONFIG_IDE_PROC_FS
978 .proc = idedisk_proc, 987 .proc = idedisk_proc,
988 .settings = idedisk_settings,
979#endif 989#endif
980}; 990};
981 991
@@ -1056,19 +1066,18 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
1056 struct block_device *bdev = inode->i_bdev; 1066 struct block_device *bdev = inode->i_bdev;
1057 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); 1067 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1058 ide_drive_t *drive = idkp->drive; 1068 ide_drive_t *drive = idkp->drive;
1059 int err, (*setfunc)(ide_drive_t *, int); 1069 int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
1060 u8 *val;
1061 1070
1062 switch (cmd) { 1071 switch (cmd) {
1063 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; 1072 case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
1064 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; 1073 case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
1065 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; 1074 case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
1066 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; 1075 case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
1067 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; 1076 case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
1068 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; 1077 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1069 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; 1078 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1070 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; 1079 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1071 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; 1080 case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
1072 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; 1081 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1073 } 1082 }
1074 1083
@@ -1077,7 +1086,7 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
1077read_val: 1086read_val:
1078 mutex_lock(&ide_setting_mtx); 1087 mutex_lock(&ide_setting_mtx);
1079 spin_lock_irqsave(&ide_lock, flags); 1088 spin_lock_irqsave(&ide_lock, flags);
1080 err = *val; 1089 err = getfunc(drive);
1081 spin_unlock_irqrestore(&ide_lock, flags); 1090 spin_unlock_irqrestore(&ide_lock, flags);
1082 mutex_unlock(&ide_setting_mtx); 1091 mutex_unlock(&ide_setting_mtx);
1083 return err >= 0 ? put_user(err, (long __user *)arg) : err; 1092 return err >= 0 ? put_user(err, (long __user *)arg) : err;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 597459c81d5f..673644fdb6f2 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1007,21 +1007,32 @@ static int idefloppy_identify_device(ide_drive_t *drive, u16 *id)
1007} 1007}
1008 1008
1009#ifdef CONFIG_IDE_PROC_FS 1009#ifdef CONFIG_IDE_PROC_FS
1010static void idefloppy_add_settings(ide_drive_t *drive) 1010ide_devset_rw(bios_cyl, 0, 1023, bios_cyl);
1011ide_devset_rw(bios_head, 0, 255, bios_head);
1012ide_devset_rw(bios_sect, 0, 63, bios_sect);
1013
1014static int get_ticks(ide_drive_t *drive)
1011{ 1015{
1012 idefloppy_floppy_t *floppy = drive->driver_data; 1016 idefloppy_floppy_t *floppy = drive->driver_data;
1017 return floppy->ticks;
1018}
1013 1019
1014 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, 1020static int set_ticks(ide_drive_t *drive, int arg)
1015 &drive->bios_cyl, NULL); 1021{
1016 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, 1022 idefloppy_floppy_t *floppy = drive->driver_data;
1017 &drive->bios_head, NULL); 1023 floppy->ticks = arg;
1018 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, 1024 return 0;
1019 &drive->bios_sect, NULL);
1020 ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
1021 &floppy->ticks, NULL);
1022} 1025}
1023#else 1026
1024static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } 1027IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks);
1028
1029static const struct ide_devset *idefloppy_settings[] = {
1030 &ide_devset_bios_cyl,
1031 &ide_devset_bios_head,
1032 &ide_devset_bios_sect,
1033 &ide_devset_ticks,
1034 NULL
1035};
1025#endif 1036#endif
1026 1037
1027static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) 1038static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
@@ -1063,7 +1074,6 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
1063 (void) ide_floppy_get_capacity(drive); 1074 (void) ide_floppy_get_capacity(drive);
1064 1075
1065 ide_proc_register_driver(drive, floppy->driver); 1076 ide_proc_register_driver(drive, floppy->driver);
1066 idefloppy_add_settings(drive);
1067} 1077}
1068 1078
1069static void ide_floppy_remove(ide_drive_t *drive) 1079static void ide_floppy_remove(ide_drive_t *drive)
@@ -1126,6 +1136,7 @@ static ide_driver_t idefloppy_driver = {
1126 .error = __ide_error, 1136 .error = __ide_error,
1127#ifdef CONFIG_IDE_PROC_FS 1137#ifdef CONFIG_IDE_PROC_FS
1128 .proc = idefloppy_proc, 1138 .proc = idefloppy_proc,
1139 .settings = idefloppy_settings,
1129#endif 1140#endif
1130}; 1141};
1131 1142
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 9926e12783bb..62f7e1ef10c1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1332,8 +1332,6 @@ static void hwif_register_devices(ide_hwif_t *hwif)
1332 if (!drive->present) 1332 if (!drive->present)
1333 continue; 1333 continue;
1334 1334
1335 ide_add_generic_settings(drive);
1336
1337 snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); 1335 snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
1338 dev->parent = &hwif->gendev; 1336 dev->parent = &hwif->gendev;
1339 dev->bus = &ide_bus_type; 1337 dev->bus = &ide_bus_type;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 7a64aedfa648..5634b3971d21 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -114,140 +114,24 @@ static int proc_ide_read_identify
114} 114}
115 115
116/** 116/**
117 * __ide_add_setting - add an ide setting option 117 * ide_find_setting - find a specific setting
118 * @drive: drive to use 118 * @st: setting table pointer
119 * @name: setting name 119 * @name: setting name
120 * @rw: true if the function is read write
121 * @data_type: type of data
122 * @min: range minimum
123 * @max: range maximum
124 * @mul_factor: multiplication scale
125 * @div_factor: divison scale
126 * @data: private data field
127 * @set: setting
128 * @auto_remove: setting auto removal flag
129 * 120 *
130 * Removes the setting named from the device if it is present. 121 * Scan's the setting table for a matching entry and returns
131 * The function takes the settings_lock to protect against
132 * parallel changes. This function must not be called from IRQ
133 * context. Returns 0 on success or -1 on failure.
134 *
135 * BUGS: This code is seriously over-engineered. There is also
136 * magic about how the driver specific features are setup. If
137 * a driver is attached we assume the driver settings are auto
138 * remove.
139 */
140
141static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
142{
143 ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
144
145 mutex_lock(&ide_setting_mtx);
146 while ((*p) && strcmp((*p)->name, name) < 0)
147 p = &((*p)->next);
148 if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
149 goto abort;
150 if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
151 goto abort;
152 strcpy(setting->name, name);
153 setting->rw = rw;
154 setting->data_type = data_type;
155 setting->min = min;
156 setting->max = max;
157 setting->mul_factor = mul_factor;
158 setting->div_factor = div_factor;
159 setting->data = data;
160 setting->set = set;
161
162 setting->next = *p;
163 if (auto_remove)
164 setting->auto_remove = 1;
165 *p = setting;
166 mutex_unlock(&ide_setting_mtx);
167 return 0;
168abort:
169 mutex_unlock(&ide_setting_mtx);
170 kfree(setting);
171 return -1;
172}
173
174int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
175{
176 return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
177}
178
179EXPORT_SYMBOL(ide_add_setting);
180
181/**
182 * __ide_remove_setting - remove an ide setting option
183 * @drive: drive to use
184 * @name: setting name
185 *
186 * Removes the setting named from the device if it is present.
187 * The caller must hold the setting semaphore.
188 */
189
190static void __ide_remove_setting(ide_drive_t *drive, char *name)
191{
192 ide_settings_t **p, *setting;
193
194 p = (ide_settings_t **) &drive->settings;
195
196 while ((*p) && strcmp((*p)->name, name))
197 p = &((*p)->next);
198 setting = (*p);
199 if (setting == NULL)
200 return;
201
202 (*p) = setting->next;
203
204 kfree(setting->name);
205 kfree(setting);
206}
207
208/**
209 * auto_remove_settings - remove driver specific settings
210 * @drive: drive
211 *
212 * Automatically remove all the driver specific settings for this
213 * drive. This function may not be called from IRQ context. The
214 * caller must hold ide_setting_mtx.
215 */
216
217static void auto_remove_settings(ide_drive_t *drive)
218{
219 ide_settings_t *setting;
220repeat:
221 setting = drive->settings;
222 while (setting) {
223 if (setting->auto_remove) {
224 __ide_remove_setting(drive, setting->name);
225 goto repeat;
226 }
227 setting = setting->next;
228 }
229}
230
231/**
232 * ide_find_setting_by_name - find a drive specific setting
233 * @drive: drive to scan
234 * @name: setting name
235 *
236 * Scan's the device setting table for a matching entry and returns
237 * this or NULL if no entry is found. The caller must hold the 122 * this or NULL if no entry is found. The caller must hold the
238 * setting semaphore 123 * setting semaphore
239 */ 124 */
240 125
241static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) 126static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
127 char *name)
242{ 128{
243 ide_settings_t *setting = drive->settings; 129 while (*st) {
244 130 if (strcmp((*st)->name, name) == 0)
245 while (setting) {
246 if (strcmp(setting->name, name) == 0)
247 break; 131 break;
248 setting = setting->next; 132 st++;
249 } 133 }
250 return setting; 134 return *st;
251} 135}
252 136
253/** 137/**
@@ -263,26 +147,19 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
263 * be told apart 147 * be told apart
264 */ 148 */
265 149
266static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) 150static int ide_read_setting(ide_drive_t *drive,
151 const struct ide_devset *setting)
267{ 152{
268 int val = -EINVAL; 153 int val = -EINVAL;
269 unsigned long flags; 154
155 if ((setting->flags & S_READ)) {
156 unsigned long flags;
270 157
271 if ((setting->rw & SETTING_READ)) {
272 spin_lock_irqsave(&ide_lock, flags); 158 spin_lock_irqsave(&ide_lock, flags);
273 switch (setting->data_type) { 159 val = setting->get(drive);
274 case TYPE_BYTE:
275 val = *((u8 *) setting->data);
276 break;
277 case TYPE_SHORT:
278 val = *((u16 *) setting->data);
279 break;
280 case TYPE_INT:
281 val = *((u32 *) setting->data);
282 break;
283 }
284 spin_unlock_irqrestore(&ide_lock, flags); 160 spin_unlock_irqrestore(&ide_lock, flags);
285 } 161 }
162
286 return val; 163 return val;
287} 164}
288 165
@@ -304,33 +181,26 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
304 * The current scheme of polling is kludgy, though safe enough. 181 * The current scheme of polling is kludgy, though safe enough.
305 */ 182 */
306 183
307static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) 184static int ide_write_setting(ide_drive_t *drive,
185 const struct ide_devset *setting, int val)
308{ 186{
309 if (!capable(CAP_SYS_ADMIN)) 187 if (!capable(CAP_SYS_ADMIN))
310 return -EACCES; 188 return -EACCES;
311 if (setting->set) 189 if (setting->set && (setting->flags & S_NOLOCK))
312 return setting->set(drive, val); 190 return setting->set(drive, val);
313 if (!(setting->rw & SETTING_WRITE)) 191 if (!(setting->flags & S_WRITE))
314 return -EPERM; 192 return -EPERM;
315 if (val < setting->min || val > setting->max) 193 if (val < setting->min || val > setting->max)
316 return -EINVAL; 194 return -EINVAL;
317 if (ide_spin_wait_hwgroup(drive)) 195 if (ide_spin_wait_hwgroup(drive))
318 return -EBUSY; 196 return -EBUSY;
319 switch (setting->data_type) { 197 setting->set(drive, val);
320 case TYPE_BYTE:
321 *((u8 *) setting->data) = val;
322 break;
323 case TYPE_SHORT:
324 *((u16 *) setting->data) = val;
325 break;
326 case TYPE_INT:
327 *((u32 *) setting->data) = val;
328 break;
329 }
330 spin_unlock_irq(&ide_lock); 198 spin_unlock_irq(&ide_lock);
331 return 0; 199 return 0;
332} 200}
333 201
202static ide_devset_get(xfer_rate, current_speed);
203
334static int set_xfer_rate (ide_drive_t *drive, int arg) 204static int set_xfer_rate (ide_drive_t *drive, int arg)
335{ 205{
336 ide_task_t task; 206 ide_task_t task;
@@ -355,29 +225,30 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
355 return err; 225 return err;
356} 226}
357 227
358/** 228ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate);
359 * ide_add_generic_settings - generic ide settings 229ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit);
360 * @drive: drive being configured 230ide_devset_rw_nolock(keepsettings, 0, 1, ksettings);
361 * 231ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq);
362 * Add the generic parts of the system settings to the /proc files. 232ide_devset_rw_nolock(using_dma, 0, 1, using_dma);
363 * The caller must not be holding the ide_setting_mtx. 233
364 */ 234ide_devset_w_nolock(pio_mode, 0, 255, pio_mode);
365 235
366void ide_add_generic_settings (ide_drive_t *drive) 236ide_devset_rw(init_speed, 0, 70, init_speed);
367{ 237ide_devset_rw(nice1, 0, 1, nice1);
368/* 238ide_devset_rw(number, 0, 3, dn);
369 * drive setting name read/write access data type min max mul_factor div_factor data pointer set function 239
370 */ 240static const struct ide_devset *ide_generic_settings[] = {
371 __ide_add_setting(drive, "io_32bit", SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); 241 &ide_devset_current_speed,
372 __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, set_ksettings, 0); 242 &ide_devset_init_speed,
373 __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); 243 &ide_devset_io_32bit,
374 __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); 244 &ide_devset_keepsettings,
375 __ide_add_setting(drive, "unmaskirq", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, set_unmaskirq, 0); 245 &ide_devset_nice1,
376 __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); 246 &ide_devset_number,
377 __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); 247 &ide_devset_pio_mode,
378 __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); 248 &ide_devset_unmaskirq,
379 __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); 249 &ide_devset_using_dma,
380} 250 NULL
251};
381 252
382static void proc_ide_settings_warn(void) 253static void proc_ide_settings_warn(void)
383{ 254{
@@ -394,19 +265,31 @@ static void proc_ide_settings_warn(void)
394static int proc_ide_read_settings 265static int proc_ide_read_settings
395 (char *page, char **start, off_t off, int count, int *eof, void *data) 266 (char *page, char **start, off_t off, int count, int *eof, void *data)
396{ 267{
268 const struct ide_devset *setting, **g, **d;
397 ide_drive_t *drive = (ide_drive_t *) data; 269 ide_drive_t *drive = (ide_drive_t *) data;
398 ide_settings_t *setting = (ide_settings_t *) drive->settings;
399 char *out = page; 270 char *out = page;
400 int len, rc, mul_factor, div_factor; 271 int len, rc, mul_factor, div_factor;
401 272
402 proc_ide_settings_warn(); 273 proc_ide_settings_warn();
403 274
404 mutex_lock(&ide_setting_mtx); 275 mutex_lock(&ide_setting_mtx);
276 g = ide_generic_settings;
277 d = drive->settings;
405 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); 278 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
406 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); 279 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
407 while (setting) { 280 while (*g || (d && *d)) {
408 mul_factor = setting->mul_factor; 281 /* read settings in the alphabetical order */
409 div_factor = setting->div_factor; 282 if (*g && d && *d) {
283 if (strcmp((*d)->name, (*g)->name) < 0)
284 setting = *d++;
285 else
286 setting = *g++;
287 } else if (d && *d) {
288 setting = *d++;
289 } else
290 setting = *g++;
291 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
292 div_factor = setting->divf ? setting->divf(drive) : 1;
410 out += sprintf(out, "%-24s", setting->name); 293 out += sprintf(out, "%-24s", setting->name);
411 rc = ide_read_setting(drive, setting); 294 rc = ide_read_setting(drive, setting);
412 if (rc >= 0) 295 if (rc >= 0)
@@ -414,12 +297,11 @@ static int proc_ide_read_settings
414 else 297 else
415 out += sprintf(out, "%-16s", "write-only"); 298 out += sprintf(out, "%-16s", "write-only");
416 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); 299 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
417 if (setting->rw & SETTING_READ) 300 if (setting->flags & S_READ)
418 out += sprintf(out, "r"); 301 out += sprintf(out, "r");
419 if (setting->rw & SETTING_WRITE) 302 if (setting->flags & S_WRITE)
420 out += sprintf(out, "w"); 303 out += sprintf(out, "w");
421 out += sprintf(out, "\n"); 304 out += sprintf(out, "\n");
422 setting = setting->next;
423 } 305 }
424 len = out - page; 306 len = out - page;
425 mutex_unlock(&ide_setting_mtx); 307 mutex_unlock(&ide_setting_mtx);
@@ -433,9 +315,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
433{ 315{
434 ide_drive_t *drive = (ide_drive_t *) data; 316 ide_drive_t *drive = (ide_drive_t *) data;
435 char name[MAX_LEN + 1]; 317 char name[MAX_LEN + 1];
436 int for_real = 0; 318 int for_real = 0, mul_factor, div_factor;
437 unsigned long n; 319 unsigned long n;
438 ide_settings_t *setting; 320
321 const struct ide_devset *setting;
439 char *buf, *s; 322 char *buf, *s;
440 323
441 if (!capable(CAP_SYS_ADMIN)) 324 if (!capable(CAP_SYS_ADMIN))
@@ -503,13 +386,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
503 } 386 }
504 387
505 mutex_lock(&ide_setting_mtx); 388 mutex_lock(&ide_setting_mtx);
506 setting = ide_find_setting_by_name(drive, name); 389 /* generic settings first, then driver specific ones */
390 setting = ide_find_setting(ide_generic_settings, name);
507 if (!setting) { 391 if (!setting) {
508 mutex_unlock(&ide_setting_mtx); 392 if (drive->settings)
509 goto parse_error; 393 setting = ide_find_setting(drive->settings, name);
394 if (!setting) {
395 mutex_unlock(&ide_setting_mtx);
396 goto parse_error;
397 }
398 }
399 if (for_real) {
400 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
401 div_factor = setting->divf ? setting->divf(drive) : 1;
402 ide_write_setting(drive, setting, val * div_factor / mul_factor);
510 } 403 }
511 if (for_real)
512 ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
513 mutex_unlock(&ide_setting_mtx); 404 mutex_unlock(&ide_setting_mtx);
514 } 405 }
515 } while (!for_real++); 406 } while (!for_real++);
@@ -680,6 +571,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
680 571
681void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) 572void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
682{ 573{
574 mutex_lock(&ide_setting_mtx);
575 drive->settings = driver->settings;
576 mutex_unlock(&ide_setting_mtx);
577
683 ide_add_proc_entries(drive->proc, driver->proc, drive); 578 ide_add_proc_entries(drive->proc, driver->proc, drive);
684} 579}
685 580
@@ -716,7 +611,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
716 * OTOH both ide_{read,write}_setting are only ever used under 611 * OTOH both ide_{read,write}_setting are only ever used under
717 * ide_setting_mtx. 612 * ide_setting_mtx.
718 */ 613 */
719 auto_remove_settings(drive); 614 drive->settings = NULL;
720 spin_unlock_irqrestore(&ide_lock, flags); 615 spin_unlock_irqrestore(&ide_lock, flags);
721 mutex_unlock(&ide_setting_mtx); 616 mutex_unlock(&ide_setting_mtx);
722} 617}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f41983e4a4e4..7037accb0589 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2410,28 +2410,56 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
2410} 2410}
2411 2411
2412#ifdef CONFIG_IDE_PROC_FS 2412#ifdef CONFIG_IDE_PROC_FS
2413static void idetape_add_settings(ide_drive_t *drive) 2413#define ide_tape_devset_get(name, field) \
2414{ 2414static int get_##name(ide_drive_t *drive) \
2415 idetape_tape_t *tape = drive->driver_data; 2415{ \
2416 2416 idetape_tape_t *tape = drive->driver_data; \
2417 ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 2417 return tape->field; \
2418 1, 2, (u16 *)&tape->caps[16], NULL); 2418}
2419 ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 2419
2420 1, 1, (u16 *)&tape->caps[14], NULL); 2420#define ide_tape_devset_set(name, field) \
2421 ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff, 2421static int set_##name(ide_drive_t *drive, int arg) \
2422 1, 1024, &tape->buffer_size, NULL); 2422{ \
2423 ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, 2423 idetape_tape_t *tape = drive->driver_data; \
2424 IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq, 2424 tape->field = arg; \
2425 NULL); 2425 return 0; \
2426 ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 2426}
2427 1, &drive->dsc_overlap, NULL); 2427
2428 ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 2428#define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \
2429 1, 1, &tape->avg_speed, NULL); 2429ide_tape_devset_get(_name, _field) \
2430 ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 2430ide_tape_devset_set(_name, _field) \
2431 1, &tape->debug_mask, NULL); 2431__IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf)
2432} 2432
2433#else 2433#define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \
2434static inline void idetape_add_settings(ide_drive_t *drive) { ; } 2434ide_tape_devset_get(_name, _field) \
2435__IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf)
2436
2437static int mulf_tdsc(ide_drive_t *drive) { return 1000; }
2438static int divf_tdsc(ide_drive_t *drive) { return HZ; }
2439static int divf_buffer(ide_drive_t *drive) { return 2; }
2440static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
2441
2442ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
2443
2444ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL);
2445ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
2446 best_dsc_rw_freq, mulf_tdsc, divf_tdsc);
2447
2448ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL);
2449ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL);
2450ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer);
2451ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size);
2452
2453static const struct ide_devset *idetape_settings[] = {
2454 &ide_devset_avg_speed,
2455 &ide_devset_buffer,
2456 &ide_devset_buffer_size,
2457 &ide_devset_debug_mask,
2458 &ide_devset_dsc_overlap,
2459 &ide_devset_speed,
2460 &ide_devset_tdsc,
2461 NULL
2462};
2435#endif 2463#endif
2436 2464
2437/* 2465/*
@@ -2515,7 +2543,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
2515 drive->using_dma ? ", DMA":""); 2543 drive->using_dma ? ", DMA":"");
2516 2544
2517 ide_proc_register_driver(drive, tape->driver); 2545 ide_proc_register_driver(drive, tape->driver);
2518 idetape_add_settings(drive);
2519} 2546}
2520 2547
2521static void ide_tape_remove(ide_drive_t *drive) 2548static void ide_tape_remove(ide_drive_t *drive)
@@ -2586,6 +2613,7 @@ static ide_driver_t idetape_driver = {
2586 .error = __ide_error, 2613 .error = __ide_error,
2587#ifdef CONFIG_IDE_PROC_FS 2614#ifdef CONFIG_IDE_PROC_FS
2588 .proc = idetape_proc, 2615 .proc = idetape_proc,
2616 .settings = idetape_settings,
2589#endif 2617#endif
2590}; 2618};
2591 2619
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8e0c9f27ae4a..eb64e942f58b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -287,6 +287,8 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
287 287
288EXPORT_SYMBOL(ide_spin_wait_hwgroup); 288EXPORT_SYMBOL(ide_spin_wait_hwgroup);
289 289
290ide_devset_get(io_32bit, io_32bit);
291
290int set_io_32bit(ide_drive_t *drive, int arg) 292int set_io_32bit(ide_drive_t *drive, int arg)
291{ 293{
292 if (drive->no_io_32bit) 294 if (drive->no_io_32bit)
@@ -305,6 +307,8 @@ int set_io_32bit(ide_drive_t *drive, int arg)
305 return 0; 307 return 0;
306} 308}
307 309
310ide_devset_get(ksettings, keep_settings);
311
308int set_ksettings(ide_drive_t *drive, int arg) 312int set_ksettings(ide_drive_t *drive, int arg)
309{ 313{
310 if (arg < 0 || arg > 1) 314 if (arg < 0 || arg > 1)
@@ -318,6 +322,8 @@ int set_ksettings(ide_drive_t *drive, int arg)
318 return 0; 322 return 0;
319} 323}
320 324
325ide_devset_get(using_dma, using_dma);
326
321int set_using_dma(ide_drive_t *drive, int arg) 327int set_using_dma(ide_drive_t *drive, int arg)
322{ 328{
323#ifdef CONFIG_BLK_DEV_IDEDMA 329#ifdef CONFIG_BLK_DEV_IDEDMA
@@ -394,6 +400,8 @@ int set_pio_mode(ide_drive_t *drive, int arg)
394 return 0; 400 return 0;
395} 401}
396 402
403ide_devset_get(unmaskirq, unmask);
404
397int set_unmaskirq(ide_drive_t *drive, int arg) 405int set_unmaskirq(ide_drive_t *drive, int arg)
398{ 406{
399 if (drive->no_unmask) 407 if (drive->no_unmask)
@@ -555,14 +563,13 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
555{ 563{
556 unsigned long flags; 564 unsigned long flags;
557 ide_driver_t *drv; 565 ide_driver_t *drv;
558 int err = 0, (*setfunc)(ide_drive_t *, int); 566 int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
559 u8 *val;
560 567
561 switch (cmd) { 568 switch (cmd) {
562 case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; 569 case HDIO_GET_32BIT: getfunc = get_io_32bit; goto read_val;
563 case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; 570 case HDIO_GET_KEEPSETTINGS: getfunc = get_ksettings; goto read_val;
564 case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; 571 case HDIO_GET_UNMASKINTR: getfunc = get_unmaskirq; goto read_val;
565 case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; 572 case HDIO_GET_DMA: getfunc = get_using_dma; goto read_val;
566 case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; 573 case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
567 case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; 574 case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
568 case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; 575 case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
@@ -638,7 +645,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
638read_val: 645read_val:
639 mutex_lock(&ide_setting_mtx); 646 mutex_lock(&ide_setting_mtx);
640 spin_lock_irqsave(&ide_lock, flags); 647 spin_lock_irqsave(&ide_lock, flags);
641 err = *val; 648 err = getfunc(drive);
642 spin_unlock_irqrestore(&ide_lock, flags); 649 spin_unlock_irqrestore(&ide_lock, flags);
643 mutex_unlock(&ide_setting_mtx); 650 mutex_unlock(&ide_setting_mtx);
644 return err >= 0 ? put_user(err, (long __user *)arg) : err; 651 return err >= 0 ? put_user(err, (long __user *)arg) : err;