diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-09 18:01:10 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-09 18:01:10 -0400 |
commit | 7662d046df09e80680b77b68de896beab45e675e (patch) | |
tree | ea2281c59399b3867fb37e1005a0f0e0d2170c5d | |
parent | 1497943ee692aa7519fa972d0e3a339649bf3a96 (diff) |
ide: move IDE settings handling to ide-proc.c
* move
__ide_add_setting()
ide_add_setting()
__ide_remove_setting()
auto_remove_settings()
ide_find_setting_by_name()
ide_read_setting()
ide_write_setting()
set_xfer_rate()
ide_add_generic_settings()
ide_register_subdriver()
ide_unregister_subdriver()
from ide.c to ide-proc.c
* set_{io_32bit,pio_mode,using_dma}() cannot be marked static now, fix it
* rename ide_[un]register_subdriver() to ide_proc_[un]register_driver(),
update device drivers to use new names
* add CONFIG_IDE_PROC_FS=n versions of ide_proc_[un]register_driver()
and ide_add_generic_settings()
* make ide_find_setting_by_name(), ide_{read,write}_setting()
and ide_{add,remove}_proc_entries() static
* cover IDE settings code in device drivers with CONFIG_IDE_PROC_FS #ifdef,
also while at it cover with CONFIG_IDE_PROC_FS #ifdef ide_driver_t.proc
* remove bogus comment from ide.h
* cover with CONFIG_IDE_PROC_FS #ifdef .proc and .settings in ide_drive_t
Besides saner code this patch results in the IDE core smaller by ~2 kB
(on x86-32) and IDE disk driver by ~1 kB (ditto) when CONFIG_IDE_PROC_FS=n.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-cd.c | 14 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 16 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 16 | ||||
-rw-r--r-- | drivers/ide/ide-proc.c | 310 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 17 | ||||
-rw-r--r-- | drivers/ide/ide.c | 313 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.c | 16 | ||||
-rw-r--r-- | include/linux/ide.h | 39 |
8 files changed, 378 insertions, 363 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 29408cfd9869..252ab8295edf 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -3059,10 +3059,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) | |||
3059 | return nslots; | 3059 | return nslots; |
3060 | } | 3060 | } |
3061 | 3061 | ||
3062 | #ifdef CONFIG_IDE_PROC_FS | ||
3062 | static void ide_cdrom_add_settings(ide_drive_t *drive) | 3063 | static void ide_cdrom_add_settings(ide_drive_t *drive) |
3063 | { | 3064 | { |
3064 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); | 3065 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); |
3065 | } | 3066 | } |
3067 | #else | ||
3068 | static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } | ||
3069 | #endif | ||
3066 | 3070 | ||
3067 | /* | 3071 | /* |
3068 | * standard prep_rq_fn that builds 10 byte cmds | 3072 | * standard prep_rq_fn that builds 10 byte cmds |
@@ -3291,7 +3295,7 @@ static void ide_cd_remove(ide_drive_t *drive) | |||
3291 | { | 3295 | { |
3292 | struct cdrom_info *info = drive->driver_data; | 3296 | struct cdrom_info *info = drive->driver_data; |
3293 | 3297 | ||
3294 | ide_unregister_subdriver(drive, info->driver); | 3298 | ide_proc_unregister_driver(drive, info->driver); |
3295 | 3299 | ||
3296 | del_gendisk(info->disk); | 3300 | del_gendisk(info->disk); |
3297 | 3301 | ||
@@ -3336,8 +3340,6 @@ static ide_proc_entry_t idecd_proc[] = { | |||
3336 | { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, | 3340 | { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, |
3337 | { NULL, 0, NULL, NULL } | 3341 | { NULL, 0, NULL, NULL } |
3338 | }; | 3342 | }; |
3339 | #else | ||
3340 | # define idecd_proc NULL | ||
3341 | #endif | 3343 | #endif |
3342 | 3344 | ||
3343 | static ide_driver_t ide_cdrom_driver = { | 3345 | static ide_driver_t ide_cdrom_driver = { |
@@ -3355,7 +3357,9 @@ static ide_driver_t ide_cdrom_driver = { | |||
3355 | .end_request = ide_end_request, | 3357 | .end_request = ide_end_request, |
3356 | .error = __ide_error, | 3358 | .error = __ide_error, |
3357 | .abort = __ide_abort, | 3359 | .abort = __ide_abort, |
3360 | #ifdef CONFIG_IDE_PROC_FS | ||
3358 | .proc = idecd_proc, | 3361 | .proc = idecd_proc, |
3362 | #endif | ||
3359 | }; | 3363 | }; |
3360 | 3364 | ||
3361 | static int idecd_open(struct inode * inode, struct file * file) | 3365 | static int idecd_open(struct inode * inode, struct file * file) |
@@ -3517,7 +3521,7 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
3517 | 3521 | ||
3518 | ide_init_disk(g, drive); | 3522 | ide_init_disk(g, drive); |
3519 | 3523 | ||
3520 | ide_register_subdriver(drive, &ide_cdrom_driver); | 3524 | ide_proc_register_driver(drive, &ide_cdrom_driver); |
3521 | 3525 | ||
3522 | kref_init(&info->kref); | 3526 | kref_init(&info->kref); |
3523 | 3527 | ||
@@ -3534,7 +3538,7 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
3534 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; | 3538 | g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; |
3535 | if (ide_cdrom_setup(drive)) { | 3539 | if (ide_cdrom_setup(drive)) { |
3536 | struct cdrom_device_info *devinfo = &info->devinfo; | 3540 | struct cdrom_device_info *devinfo = &info->devinfo; |
3537 | ide_unregister_subdriver(drive, &ide_cdrom_driver); | 3541 | ide_proc_unregister_driver(drive, &ide_cdrom_driver); |
3538 | kfree(info->buffer); | 3542 | kfree(info->buffer); |
3539 | kfree(info->toc); | 3543 | kfree(info->toc); |
3540 | kfree(info->changer_info); | 3544 | kfree(info->changer_info); |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index fb162cb3ebf5..7fff773f2df7 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -560,7 +560,6 @@ static sector_t idedisk_capacity (ide_drive_t *drive) | |||
560 | } | 560 | } |
561 | 561 | ||
562 | #ifdef CONFIG_IDE_PROC_FS | 562 | #ifdef CONFIG_IDE_PROC_FS |
563 | |||
564 | static int smart_enable(ide_drive_t *drive) | 563 | static int smart_enable(ide_drive_t *drive) |
565 | { | 564 | { |
566 | ide_task_t args; | 565 | ide_task_t args; |
@@ -678,11 +677,6 @@ static ide_proc_entry_t idedisk_proc[] = { | |||
678 | { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, | 677 | { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, |
679 | { NULL, 0, NULL, NULL } | 678 | { NULL, 0, NULL, NULL } |
680 | }; | 679 | }; |
681 | |||
682 | #else | ||
683 | |||
684 | #define idedisk_proc NULL | ||
685 | |||
686 | #endif /* CONFIG_IDE_PROC_FS */ | 680 | #endif /* CONFIG_IDE_PROC_FS */ |
687 | 681 | ||
688 | static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) | 682 | static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) |
@@ -881,6 +875,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) | |||
881 | return 0; | 875 | return 0; |
882 | } | 876 | } |
883 | 877 | ||
878 | #ifdef CONFIG_IDE_PROC_FS | ||
884 | static void idedisk_add_settings(ide_drive_t *drive) | 879 | static void idedisk_add_settings(ide_drive_t *drive) |
885 | { | 880 | { |
886 | struct hd_driveid *id = drive->id; | 881 | struct hd_driveid *id = drive->id; |
@@ -898,6 +893,9 @@ static void idedisk_add_settings(ide_drive_t *drive) | |||
898 | ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); | 893 | ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); |
899 | ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); | 894 | ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); |
900 | } | 895 | } |
896 | #else | ||
897 | static inline void idedisk_add_settings(ide_drive_t *drive) { ; } | ||
898 | #endif | ||
901 | 899 | ||
902 | static void idedisk_setup (ide_drive_t *drive) | 900 | static void idedisk_setup (ide_drive_t *drive) |
903 | { | 901 | { |
@@ -1016,7 +1014,7 @@ static void ide_disk_remove(ide_drive_t *drive) | |||
1016 | struct ide_disk_obj *idkp = drive->driver_data; | 1014 | struct ide_disk_obj *idkp = drive->driver_data; |
1017 | struct gendisk *g = idkp->disk; | 1015 | struct gendisk *g = idkp->disk; |
1018 | 1016 | ||
1019 | ide_unregister_subdriver(drive, idkp->driver); | 1017 | ide_proc_unregister_driver(drive, idkp->driver); |
1020 | 1018 | ||
1021 | del_gendisk(g); | 1019 | del_gendisk(g); |
1022 | 1020 | ||
@@ -1081,7 +1079,9 @@ static ide_driver_t idedisk_driver = { | |||
1081 | .end_request = ide_end_request, | 1079 | .end_request = ide_end_request, |
1082 | .error = __ide_error, | 1080 | .error = __ide_error, |
1083 | .abort = __ide_abort, | 1081 | .abort = __ide_abort, |
1082 | #ifdef CONFIG_IDE_PROC_FS | ||
1084 | .proc = idedisk_proc, | 1083 | .proc = idedisk_proc, |
1084 | #endif | ||
1085 | }; | 1085 | }; |
1086 | 1086 | ||
1087 | static int idedisk_open(struct inode *inode, struct file *filp) | 1087 | static int idedisk_open(struct inode *inode, struct file *filp) |
@@ -1257,7 +1257,7 @@ static int ide_disk_probe(ide_drive_t *drive) | |||
1257 | 1257 | ||
1258 | ide_init_disk(g, drive); | 1258 | ide_init_disk(g, drive); |
1259 | 1259 | ||
1260 | ide_register_subdriver(drive, &idedisk_driver); | 1260 | ide_proc_register_driver(drive, &idedisk_driver); |
1261 | 1261 | ||
1262 | kref_init(&idkp->kref); | 1262 | kref_init(&idkp->kref); |
1263 | 1263 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 38fe45cf4019..f429be88c4f9 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -1811,6 +1811,7 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) | |||
1811 | return 0; | 1811 | return 0; |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | #ifdef CONFIG_IDE_PROC_FS | ||
1814 | static void idefloppy_add_settings(ide_drive_t *drive) | 1815 | static void idefloppy_add_settings(ide_drive_t *drive) |
1815 | { | 1816 | { |
1816 | idefloppy_floppy_t *floppy = drive->driver_data; | 1817 | idefloppy_floppy_t *floppy = drive->driver_data; |
@@ -1823,6 +1824,9 @@ static void idefloppy_add_settings(ide_drive_t *drive) | |||
1823 | ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); | 1824 | ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); |
1824 | ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); | 1825 | ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); |
1825 | } | 1826 | } |
1827 | #else | ||
1828 | static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } | ||
1829 | #endif | ||
1826 | 1830 | ||
1827 | /* | 1831 | /* |
1828 | * Driver initialization. | 1832 | * Driver initialization. |
@@ -1873,7 +1877,7 @@ static void ide_floppy_remove(ide_drive_t *drive) | |||
1873 | idefloppy_floppy_t *floppy = drive->driver_data; | 1877 | idefloppy_floppy_t *floppy = drive->driver_data; |
1874 | struct gendisk *g = floppy->disk; | 1878 | struct gendisk *g = floppy->disk; |
1875 | 1879 | ||
1876 | ide_unregister_subdriver(drive, floppy->driver); | 1880 | ide_proc_unregister_driver(drive, floppy->driver); |
1877 | 1881 | ||
1878 | del_gendisk(g); | 1882 | del_gendisk(g); |
1879 | 1883 | ||
@@ -1893,7 +1897,6 @@ static void ide_floppy_release(struct kref *kref) | |||
1893 | } | 1897 | } |
1894 | 1898 | ||
1895 | #ifdef CONFIG_IDE_PROC_FS | 1899 | #ifdef CONFIG_IDE_PROC_FS |
1896 | |||
1897 | static int proc_idefloppy_read_capacity | 1900 | static int proc_idefloppy_read_capacity |
1898 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 1901 | (char *page, char **start, off_t off, int count, int *eof, void *data) |
1899 | { | 1902 | { |
@@ -1909,11 +1912,6 @@ static ide_proc_entry_t idefloppy_proc[] = { | |||
1909 | { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, | 1912 | { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, |
1910 | { NULL, 0, NULL, NULL } | 1913 | { NULL, 0, NULL, NULL } |
1911 | }; | 1914 | }; |
1912 | |||
1913 | #else | ||
1914 | |||
1915 | #define idefloppy_proc NULL | ||
1916 | |||
1917 | #endif /* CONFIG_IDE_PROC_FS */ | 1915 | #endif /* CONFIG_IDE_PROC_FS */ |
1918 | 1916 | ||
1919 | static int ide_floppy_probe(ide_drive_t *); | 1917 | static int ide_floppy_probe(ide_drive_t *); |
@@ -1933,7 +1931,9 @@ static ide_driver_t idefloppy_driver = { | |||
1933 | .end_request = idefloppy_do_end_request, | 1931 | .end_request = idefloppy_do_end_request, |
1934 | .error = __ide_error, | 1932 | .error = __ide_error, |
1935 | .abort = __ide_abort, | 1933 | .abort = __ide_abort, |
1934 | #ifdef CONFIG_IDE_PROC_FS | ||
1936 | .proc = idefloppy_proc, | 1935 | .proc = idefloppy_proc, |
1936 | #endif | ||
1937 | }; | 1937 | }; |
1938 | 1938 | ||
1939 | static int idefloppy_open(struct inode *inode, struct file *filp) | 1939 | static int idefloppy_open(struct inode *inode, struct file *filp) |
@@ -2159,7 +2159,7 @@ static int ide_floppy_probe(ide_drive_t *drive) | |||
2159 | 2159 | ||
2160 | ide_init_disk(g, drive); | 2160 | ide_init_disk(g, drive); |
2161 | 2161 | ||
2162 | ide_register_subdriver(drive, &idefloppy_driver); | 2162 | ide_proc_register_driver(drive, &idefloppy_driver); |
2163 | 2163 | ||
2164 | kref_init(&floppy->kref); | 2164 | kref_init(&floppy->kref); |
2165 | 2165 | ||
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a9e0b30fb1f2..949a6f609d84 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-1998 Mark Lord | 4 | * Copyright (C) 1997-1998 Mark Lord |
5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> | 5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> |
6 | * | ||
7 | * Some code was moved here from ide.c, see it for original copyrights. | ||
6 | */ | 8 | */ |
7 | 9 | ||
8 | /* | 10 | /* |
@@ -121,6 +123,265 @@ static int proc_ide_read_identify | |||
121 | PROC_IDE_READ_RETURN(page,start,off,count,eof,len); | 123 | PROC_IDE_READ_RETURN(page,start,off,count,eof,len); |
122 | } | 124 | } |
123 | 125 | ||
126 | /** | ||
127 | * __ide_add_setting - add an ide setting option | ||
128 | * @drive: drive to use | ||
129 | * @name: setting name | ||
130 | * @rw: true if the function is read write | ||
131 | * @data_type: type of data | ||
132 | * @min: range minimum | ||
133 | * @max: range maximum | ||
134 | * @mul_factor: multiplication scale | ||
135 | * @div_factor: divison scale | ||
136 | * @data: private data field | ||
137 | * @set: setting | ||
138 | * @auto_remove: setting auto removal flag | ||
139 | * | ||
140 | * Removes the setting named from the device if it is present. | ||
141 | * The function takes the settings_lock to protect against | ||
142 | * parallel changes. This function must not be called from IRQ | ||
143 | * context. Returns 0 on success or -1 on failure. | ||
144 | * | ||
145 | * BUGS: This code is seriously over-engineered. There is also | ||
146 | * magic about how the driver specific features are setup. If | ||
147 | * a driver is attached we assume the driver settings are auto | ||
148 | * remove. | ||
149 | */ | ||
150 | |||
151 | static 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) | ||
152 | { | ||
153 | ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; | ||
154 | |||
155 | down(&ide_setting_sem); | ||
156 | while ((*p) && strcmp((*p)->name, name) < 0) | ||
157 | p = &((*p)->next); | ||
158 | if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) | ||
159 | goto abort; | ||
160 | if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) | ||
161 | goto abort; | ||
162 | strcpy(setting->name, name); | ||
163 | setting->rw = rw; | ||
164 | setting->data_type = data_type; | ||
165 | setting->min = min; | ||
166 | setting->max = max; | ||
167 | setting->mul_factor = mul_factor; | ||
168 | setting->div_factor = div_factor; | ||
169 | setting->data = data; | ||
170 | setting->set = set; | ||
171 | |||
172 | setting->next = *p; | ||
173 | if (auto_remove) | ||
174 | setting->auto_remove = 1; | ||
175 | *p = setting; | ||
176 | up(&ide_setting_sem); | ||
177 | return 0; | ||
178 | abort: | ||
179 | up(&ide_setting_sem); | ||
180 | kfree(setting); | ||
181 | return -1; | ||
182 | } | ||
183 | |||
184 | 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) | ||
185 | { | ||
186 | return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); | ||
187 | } | ||
188 | |||
189 | EXPORT_SYMBOL(ide_add_setting); | ||
190 | |||
191 | /** | ||
192 | * __ide_remove_setting - remove an ide setting option | ||
193 | * @drive: drive to use | ||
194 | * @name: setting name | ||
195 | * | ||
196 | * Removes the setting named from the device if it is present. | ||
197 | * The caller must hold the setting semaphore. | ||
198 | */ | ||
199 | |||
200 | static void __ide_remove_setting (ide_drive_t *drive, char *name) | ||
201 | { | ||
202 | ide_settings_t **p, *setting; | ||
203 | |||
204 | p = (ide_settings_t **) &drive->settings; | ||
205 | |||
206 | while ((*p) && strcmp((*p)->name, name)) | ||
207 | p = &((*p)->next); | ||
208 | if ((setting = (*p)) == NULL) | ||
209 | return; | ||
210 | |||
211 | (*p) = setting->next; | ||
212 | |||
213 | kfree(setting->name); | ||
214 | kfree(setting); | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * auto_remove_settings - remove driver specific settings | ||
219 | * @drive: drive | ||
220 | * | ||
221 | * Automatically remove all the driver specific settings for this | ||
222 | * drive. This function may not be called from IRQ context. The | ||
223 | * caller must hold ide_setting_sem. | ||
224 | */ | ||
225 | |||
226 | static void auto_remove_settings (ide_drive_t *drive) | ||
227 | { | ||
228 | ide_settings_t *setting; | ||
229 | repeat: | ||
230 | setting = drive->settings; | ||
231 | while (setting) { | ||
232 | if (setting->auto_remove) { | ||
233 | __ide_remove_setting(drive, setting->name); | ||
234 | goto repeat; | ||
235 | } | ||
236 | setting = setting->next; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * ide_find_setting_by_name - find a drive specific setting | ||
242 | * @drive: drive to scan | ||
243 | * @name: setting name | ||
244 | * | ||
245 | * Scan's the device setting table for a matching entry and returns | ||
246 | * this or NULL if no entry is found. The caller must hold the | ||
247 | * setting semaphore | ||
248 | */ | ||
249 | |||
250 | static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) | ||
251 | { | ||
252 | ide_settings_t *setting = drive->settings; | ||
253 | |||
254 | while (setting) { | ||
255 | if (strcmp(setting->name, name) == 0) | ||
256 | break; | ||
257 | setting = setting->next; | ||
258 | } | ||
259 | return setting; | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * ide_read_setting - read an IDE setting | ||
264 | * @drive: drive to read from | ||
265 | * @setting: drive setting | ||
266 | * | ||
267 | * Read a drive setting and return the value. The caller | ||
268 | * must hold the ide_setting_sem when making this call. | ||
269 | * | ||
270 | * BUGS: the data return and error are the same return value | ||
271 | * so an error -EINVAL and true return of the same value cannot | ||
272 | * be told apart | ||
273 | */ | ||
274 | |||
275 | static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) | ||
276 | { | ||
277 | int val = -EINVAL; | ||
278 | unsigned long flags; | ||
279 | |||
280 | if ((setting->rw & SETTING_READ)) { | ||
281 | spin_lock_irqsave(&ide_lock, flags); | ||
282 | switch(setting->data_type) { | ||
283 | case TYPE_BYTE: | ||
284 | val = *((u8 *) setting->data); | ||
285 | break; | ||
286 | case TYPE_SHORT: | ||
287 | val = *((u16 *) setting->data); | ||
288 | break; | ||
289 | case TYPE_INT: | ||
290 | val = *((u32 *) setting->data); | ||
291 | break; | ||
292 | } | ||
293 | spin_unlock_irqrestore(&ide_lock, flags); | ||
294 | } | ||
295 | return val; | ||
296 | } | ||
297 | |||
298 | /** | ||
299 | * ide_write_setting - read an IDE setting | ||
300 | * @drive: drive to read from | ||
301 | * @setting: drive setting | ||
302 | * @val: value | ||
303 | * | ||
304 | * Write a drive setting if it is possible. The caller | ||
305 | * must hold the ide_setting_sem when making this call. | ||
306 | * | ||
307 | * BUGS: the data return and error are the same return value | ||
308 | * so an error -EINVAL and true return of the same value cannot | ||
309 | * be told apart | ||
310 | * | ||
311 | * FIXME: This should be changed to enqueue a special request | ||
312 | * to the driver to change settings, and then wait on a sema for completion. | ||
313 | * The current scheme of polling is kludgy, though safe enough. | ||
314 | */ | ||
315 | |||
316 | static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) | ||
317 | { | ||
318 | if (!capable(CAP_SYS_ADMIN)) | ||
319 | return -EACCES; | ||
320 | if (setting->set) | ||
321 | return setting->set(drive, val); | ||
322 | if (!(setting->rw & SETTING_WRITE)) | ||
323 | return -EPERM; | ||
324 | if (val < setting->min || val > setting->max) | ||
325 | return -EINVAL; | ||
326 | if (ide_spin_wait_hwgroup(drive)) | ||
327 | return -EBUSY; | ||
328 | switch (setting->data_type) { | ||
329 | case TYPE_BYTE: | ||
330 | *((u8 *) setting->data) = val; | ||
331 | break; | ||
332 | case TYPE_SHORT: | ||
333 | *((u16 *) setting->data) = val; | ||
334 | break; | ||
335 | case TYPE_INT: | ||
336 | *((u32 *) setting->data) = val; | ||
337 | break; | ||
338 | } | ||
339 | spin_unlock_irq(&ide_lock); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int set_xfer_rate (ide_drive_t *drive, int arg) | ||
344 | { | ||
345 | int err; | ||
346 | |||
347 | if (arg < 0 || arg > 70) | ||
348 | return -EINVAL; | ||
349 | |||
350 | err = ide_wait_cmd(drive, | ||
351 | WIN_SETFEATURES, (u8) arg, | ||
352 | SETFEATURES_XFER, 0, NULL); | ||
353 | |||
354 | if (!err && arg) { | ||
355 | ide_set_xfer_rate(drive, (u8) arg); | ||
356 | ide_driveid_update(drive); | ||
357 | } | ||
358 | return err; | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * ide_add_generic_settings - generic ide settings | ||
363 | * @drive: drive being configured | ||
364 | * | ||
365 | * Add the generic parts of the system settings to the /proc files. | ||
366 | * The caller must not be holding the ide_setting_sem. | ||
367 | */ | ||
368 | |||
369 | void ide_add_generic_settings (ide_drive_t *drive) | ||
370 | { | ||
371 | /* | ||
372 | * drive setting name read/write access data type min max mul_factor div_factor data pointer set function | ||
373 | */ | ||
374 | __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); | ||
375 | __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); | ||
376 | __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); | ||
377 | __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); | ||
378 | __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); | ||
379 | __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); | ||
380 | __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); | ||
381 | __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); | ||
382 | __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); | ||
383 | } | ||
384 | |||
124 | static void proc_ide_settings_warn(void) | 385 | static void proc_ide_settings_warn(void) |
125 | { | 386 | { |
126 | static int warned = 0; | 387 | static int warned = 0; |
@@ -399,7 +660,7 @@ static ide_proc_entry_t generic_drive_entries[] = { | |||
399 | { NULL, 0, NULL, NULL } | 660 | { NULL, 0, NULL, NULL } |
400 | }; | 661 | }; |
401 | 662 | ||
402 | void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) | 663 | static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) |
403 | { | 664 | { |
404 | struct proc_dir_entry *ent; | 665 | struct proc_dir_entry *ent; |
405 | 666 | ||
@@ -415,7 +676,7 @@ void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void | |||
415 | } | 676 | } |
416 | } | 677 | } |
417 | 678 | ||
418 | void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) | 679 | static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) |
419 | { | 680 | { |
420 | if (!dir || !p) | 681 | if (!dir || !p) |
421 | return; | 682 | return; |
@@ -425,6 +686,51 @@ void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) | |||
425 | } | 686 | } |
426 | } | 687 | } |
427 | 688 | ||
689 | void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) | ||
690 | { | ||
691 | ide_add_proc_entries(drive->proc, driver->proc, drive); | ||
692 | } | ||
693 | |||
694 | EXPORT_SYMBOL(ide_proc_register_driver); | ||
695 | |||
696 | /** | ||
697 | * ide_proc_unregister_driver - remove driver specific data | ||
698 | * @drive: drive | ||
699 | * @driver: driver | ||
700 | * | ||
701 | * Clean up the driver specific /proc files and IDE settings | ||
702 | * for a given drive. | ||
703 | * | ||
704 | * Takes ide_setting_sem and ide_lock. | ||
705 | * Caller must hold none of the locks. | ||
706 | */ | ||
707 | |||
708 | void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) | ||
709 | { | ||
710 | unsigned long flags; | ||
711 | |||
712 | ide_remove_proc_entries(drive->proc, driver->proc); | ||
713 | |||
714 | down(&ide_setting_sem); | ||
715 | spin_lock_irqsave(&ide_lock, flags); | ||
716 | /* | ||
717 | * ide_setting_sem protects the settings list | ||
718 | * ide_lock protects the use of settings | ||
719 | * | ||
720 | * so we need to hold both, ide_settings_sem because we want to | ||
721 | * modify the settings list, and ide_lock because we cannot take | ||
722 | * a setting out that is being used. | ||
723 | * | ||
724 | * OTOH both ide_{read,write}_setting are only ever used under | ||
725 | * ide_setting_sem. | ||
726 | */ | ||
727 | auto_remove_settings(drive); | ||
728 | spin_unlock_irqrestore(&ide_lock, flags); | ||
729 | up(&ide_setting_sem); | ||
730 | } | ||
731 | |||
732 | EXPORT_SYMBOL(ide_proc_unregister_driver); | ||
733 | |||
428 | static void create_proc_ide_drives(ide_hwif_t *hwif) | 734 | static void create_proc_ide_drives(ide_hwif_t *hwif) |
429 | { | 735 | { |
430 | int d; | 736 | int d; |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index fa0d22de37a7..e82bfa5e0ab8 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -4561,6 +4561,8 @@ static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) | |||
4561 | printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); | 4561 | printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); |
4562 | #endif /* IDETAPE_DEBUG_INFO */ | 4562 | #endif /* IDETAPE_DEBUG_INFO */ |
4563 | } | 4563 | } |
4564 | |||
4565 | #ifdef CONFIG_IDE_PROC_FS | ||
4564 | static void idetape_add_settings (ide_drive_t *drive) | 4566 | static void idetape_add_settings (ide_drive_t *drive) |
4565 | { | 4567 | { |
4566 | idetape_tape_t *tape = drive->driver_data; | 4568 | idetape_tape_t *tape = drive->driver_data; |
@@ -4583,6 +4585,9 @@ static void idetape_add_settings (ide_drive_t *drive) | |||
4583 | ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); | 4585 | ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); |
4584 | ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); | 4586 | ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); |
4585 | } | 4587 | } |
4588 | #else | ||
4589 | static inline void idetape_add_settings(ide_drive_t *drive) { ; } | ||
4590 | #endif | ||
4586 | 4591 | ||
4587 | /* | 4592 | /* |
4588 | * ide_setup is called to: | 4593 | * ide_setup is called to: |
@@ -4703,7 +4708,7 @@ static void ide_tape_remove(ide_drive_t *drive) | |||
4703 | { | 4708 | { |
4704 | idetape_tape_t *tape = drive->driver_data; | 4709 | idetape_tape_t *tape = drive->driver_data; |
4705 | 4710 | ||
4706 | ide_unregister_subdriver(drive, tape->driver); | 4711 | ide_proc_unregister_driver(drive, tape->driver); |
4707 | 4712 | ||
4708 | ide_unregister_region(tape->disk); | 4713 | ide_unregister_region(tape->disk); |
4709 | 4714 | ||
@@ -4731,7 +4736,6 @@ static void ide_tape_release(struct kref *kref) | |||
4731 | } | 4736 | } |
4732 | 4737 | ||
4733 | #ifdef CONFIG_IDE_PROC_FS | 4738 | #ifdef CONFIG_IDE_PROC_FS |
4734 | |||
4735 | static int proc_idetape_read_name | 4739 | static int proc_idetape_read_name |
4736 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 4740 | (char *page, char **start, off_t off, int count, int *eof, void *data) |
4737 | { | 4741 | { |
@@ -4749,11 +4753,6 @@ static ide_proc_entry_t idetape_proc[] = { | |||
4749 | { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, | 4753 | { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, |
4750 | { NULL, 0, NULL, NULL } | 4754 | { NULL, 0, NULL, NULL } |
4751 | }; | 4755 | }; |
4752 | |||
4753 | #else | ||
4754 | |||
4755 | #define idetape_proc NULL | ||
4756 | |||
4757 | #endif | 4756 | #endif |
4758 | 4757 | ||
4759 | static int ide_tape_probe(ide_drive_t *); | 4758 | static int ide_tape_probe(ide_drive_t *); |
@@ -4773,7 +4772,9 @@ static ide_driver_t idetape_driver = { | |||
4773 | .end_request = idetape_end_request, | 4772 | .end_request = idetape_end_request, |
4774 | .error = __ide_error, | 4773 | .error = __ide_error, |
4775 | .abort = __ide_abort, | 4774 | .abort = __ide_abort, |
4775 | #ifdef CONFIG_IDE_PROC_FS | ||
4776 | .proc = idetape_proc, | 4776 | .proc = idetape_proc, |
4777 | #endif | ||
4777 | }; | 4778 | }; |
4778 | 4779 | ||
4779 | /* | 4780 | /* |
@@ -4864,7 +4865,7 @@ static int ide_tape_probe(ide_drive_t *drive) | |||
4864 | 4865 | ||
4865 | ide_init_disk(g, drive); | 4866 | ide_init_disk(g, drive); |
4866 | 4867 | ||
4867 | ide_register_subdriver(drive, &idetape_driver); | 4868 | ide_proc_register_driver(drive, &idetape_driver); |
4868 | 4869 | ||
4869 | kref_init(&tape->kref); | 4870 | kref_init(&tape->kref); |
4870 | 4871 | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8793a960210c..614c5fd43cd2 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -826,178 +826,6 @@ DECLARE_MUTEX(ide_setting_sem); | |||
826 | EXPORT_SYMBOL_GPL(ide_setting_sem); | 826 | EXPORT_SYMBOL_GPL(ide_setting_sem); |
827 | 827 | ||
828 | /** | 828 | /** |
829 | * __ide_add_setting - add an ide setting option | ||
830 | * @drive: drive to use | ||
831 | * @name: setting name | ||
832 | * @rw: true if the function is read write | ||
833 | * @data_type: type of data | ||
834 | * @min: range minimum | ||
835 | * @max: range maximum | ||
836 | * @mul_factor: multiplication scale | ||
837 | * @div_factor: divison scale | ||
838 | * @data: private data field | ||
839 | * @set: setting | ||
840 | * @auto_remove: setting auto removal flag | ||
841 | * | ||
842 | * Removes the setting named from the device if it is present. | ||
843 | * The function takes the settings_lock to protect against | ||
844 | * parallel changes. This function must not be called from IRQ | ||
845 | * context. Returns 0 on success or -1 on failure. | ||
846 | * | ||
847 | * BUGS: This code is seriously over-engineered. There is also | ||
848 | * magic about how the driver specific features are setup. If | ||
849 | * a driver is attached we assume the driver settings are auto | ||
850 | * remove. | ||
851 | */ | ||
852 | |||
853 | static 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) | ||
854 | { | ||
855 | ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; | ||
856 | |||
857 | down(&ide_setting_sem); | ||
858 | while ((*p) && strcmp((*p)->name, name) < 0) | ||
859 | p = &((*p)->next); | ||
860 | if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) | ||
861 | goto abort; | ||
862 | if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) | ||
863 | goto abort; | ||
864 | strcpy(setting->name, name); | ||
865 | setting->rw = rw; | ||
866 | setting->data_type = data_type; | ||
867 | setting->min = min; | ||
868 | setting->max = max; | ||
869 | setting->mul_factor = mul_factor; | ||
870 | setting->div_factor = div_factor; | ||
871 | setting->data = data; | ||
872 | setting->set = set; | ||
873 | |||
874 | setting->next = *p; | ||
875 | if (auto_remove) | ||
876 | setting->auto_remove = 1; | ||
877 | *p = setting; | ||
878 | up(&ide_setting_sem); | ||
879 | return 0; | ||
880 | abort: | ||
881 | up(&ide_setting_sem); | ||
882 | kfree(setting); | ||
883 | return -1; | ||
884 | } | ||
885 | |||
886 | 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) | ||
887 | { | ||
888 | return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); | ||
889 | } | ||
890 | |||
891 | EXPORT_SYMBOL(ide_add_setting); | ||
892 | |||
893 | /** | ||
894 | * __ide_remove_setting - remove an ide setting option | ||
895 | * @drive: drive to use | ||
896 | * @name: setting name | ||
897 | * | ||
898 | * Removes the setting named from the device if it is present. | ||
899 | * The caller must hold the setting semaphore. | ||
900 | */ | ||
901 | |||
902 | static void __ide_remove_setting (ide_drive_t *drive, char *name) | ||
903 | { | ||
904 | ide_settings_t **p, *setting; | ||
905 | |||
906 | p = (ide_settings_t **) &drive->settings; | ||
907 | |||
908 | while ((*p) && strcmp((*p)->name, name)) | ||
909 | p = &((*p)->next); | ||
910 | if ((setting = (*p)) == NULL) | ||
911 | return; | ||
912 | |||
913 | (*p) = setting->next; | ||
914 | |||
915 | kfree(setting->name); | ||
916 | kfree(setting); | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * ide_find_setting_by_name - find a drive specific setting | ||
921 | * @drive: drive to scan | ||
922 | * @name: setting name | ||
923 | * | ||
924 | * Scan's the device setting table for a matching entry and returns | ||
925 | * this or NULL if no entry is found. The caller must hold the | ||
926 | * setting semaphore | ||
927 | */ | ||
928 | |||
929 | ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) | ||
930 | { | ||
931 | ide_settings_t *setting = drive->settings; | ||
932 | |||
933 | while (setting) { | ||
934 | if (strcmp(setting->name, name) == 0) | ||
935 | break; | ||
936 | setting = setting->next; | ||
937 | } | ||
938 | return setting; | ||
939 | } | ||
940 | |||
941 | /** | ||
942 | * auto_remove_settings - remove driver specific settings | ||
943 | * @drive: drive | ||
944 | * | ||
945 | * Automatically remove all the driver specific settings for this | ||
946 | * drive. This function may not be called from IRQ context. The | ||
947 | * caller must hold ide_setting_sem. | ||
948 | */ | ||
949 | |||
950 | static void auto_remove_settings (ide_drive_t *drive) | ||
951 | { | ||
952 | ide_settings_t *setting; | ||
953 | repeat: | ||
954 | setting = drive->settings; | ||
955 | while (setting) { | ||
956 | if (setting->auto_remove) { | ||
957 | __ide_remove_setting(drive, setting->name); | ||
958 | goto repeat; | ||
959 | } | ||
960 | setting = setting->next; | ||
961 | } | ||
962 | } | ||
963 | |||
964 | /** | ||
965 | * ide_read_setting - read an IDE setting | ||
966 | * @drive: drive to read from | ||
967 | * @setting: drive setting | ||
968 | * | ||
969 | * Read a drive setting and return the value. The caller | ||
970 | * must hold the ide_setting_sem when making this call. | ||
971 | * | ||
972 | * BUGS: the data return and error are the same return value | ||
973 | * so an error -EINVAL and true return of the same value cannot | ||
974 | * be told apart | ||
975 | */ | ||
976 | |||
977 | int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) | ||
978 | { | ||
979 | int val = -EINVAL; | ||
980 | unsigned long flags; | ||
981 | |||
982 | if ((setting->rw & SETTING_READ)) { | ||
983 | spin_lock_irqsave(&ide_lock, flags); | ||
984 | switch(setting->data_type) { | ||
985 | case TYPE_BYTE: | ||
986 | val = *((u8 *) setting->data); | ||
987 | break; | ||
988 | case TYPE_SHORT: | ||
989 | val = *((u16 *) setting->data); | ||
990 | break; | ||
991 | case TYPE_INT: | ||
992 | val = *((u32 *) setting->data); | ||
993 | break; | ||
994 | } | ||
995 | spin_unlock_irqrestore(&ide_lock, flags); | ||
996 | } | ||
997 | return val; | ||
998 | } | ||
999 | |||
1000 | /** | ||
1001 | * ide_spin_wait_hwgroup - wait for group | 829 | * ide_spin_wait_hwgroup - wait for group |
1002 | * @drive: drive in the group | 830 | * @drive: drive in the group |
1003 | * | 831 | * |
@@ -1030,52 +858,7 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive) | |||
1030 | 858 | ||
1031 | EXPORT_SYMBOL(ide_spin_wait_hwgroup); | 859 | EXPORT_SYMBOL(ide_spin_wait_hwgroup); |
1032 | 860 | ||
1033 | /** | 861 | int set_io_32bit(ide_drive_t *drive, int arg) |
1034 | * ide_write_setting - read an IDE setting | ||
1035 | * @drive: drive to read from | ||
1036 | * @setting: drive setting | ||
1037 | * @val: value | ||
1038 | * | ||
1039 | * Write a drive setting if it is possible. The caller | ||
1040 | * must hold the ide_setting_sem when making this call. | ||
1041 | * | ||
1042 | * BUGS: the data return and error are the same return value | ||
1043 | * so an error -EINVAL and true return of the same value cannot | ||
1044 | * be told apart | ||
1045 | * | ||
1046 | * FIXME: This should be changed to enqueue a special request | ||
1047 | * to the driver to change settings, and then wait on a sema for completion. | ||
1048 | * The current scheme of polling is kludgy, though safe enough. | ||
1049 | */ | ||
1050 | |||
1051 | int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) | ||
1052 | { | ||
1053 | if (!capable(CAP_SYS_ADMIN)) | ||
1054 | return -EACCES; | ||
1055 | if (setting->set) | ||
1056 | return setting->set(drive, val); | ||
1057 | if (!(setting->rw & SETTING_WRITE)) | ||
1058 | return -EPERM; | ||
1059 | if (val < setting->min || val > setting->max) | ||
1060 | return -EINVAL; | ||
1061 | if (ide_spin_wait_hwgroup(drive)) | ||
1062 | return -EBUSY; | ||
1063 | switch (setting->data_type) { | ||
1064 | case TYPE_BYTE: | ||
1065 | *((u8 *) setting->data) = val; | ||
1066 | break; | ||
1067 | case TYPE_SHORT: | ||
1068 | *((u16 *) setting->data) = val; | ||
1069 | break; | ||
1070 | case TYPE_INT: | ||
1071 | *((u32 *) setting->data) = val; | ||
1072 | break; | ||
1073 | } | ||
1074 | spin_unlock_irq(&ide_lock); | ||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | static int set_io_32bit(ide_drive_t *drive, int arg) | ||
1079 | { | 862 | { |
1080 | if (drive->no_io_32bit) | 863 | if (drive->no_io_32bit) |
1081 | return -EPERM; | 864 | return -EPERM; |
@@ -1104,7 +887,7 @@ static int set_ksettings(ide_drive_t *drive, int arg) | |||
1104 | return 0; | 887 | return 0; |
1105 | } | 888 | } |
1106 | 889 | ||
1107 | static int set_using_dma (ide_drive_t *drive, int arg) | 890 | int set_using_dma(ide_drive_t *drive, int arg) |
1108 | { | 891 | { |
1109 | #ifdef CONFIG_BLK_DEV_IDEDMA | 892 | #ifdef CONFIG_BLK_DEV_IDEDMA |
1110 | ide_hwif_t *hwif = drive->hwif; | 893 | ide_hwif_t *hwif = drive->hwif; |
@@ -1152,7 +935,7 @@ out: | |||
1152 | #endif | 935 | #endif |
1153 | } | 936 | } |
1154 | 937 | ||
1155 | static int set_pio_mode (ide_drive_t *drive, int arg) | 938 | int set_pio_mode(ide_drive_t *drive, int arg) |
1156 | { | 939 | { |
1157 | struct request rq; | 940 | struct request rq; |
1158 | 941 | ||
@@ -1186,48 +969,6 @@ static int set_unmaskirq(ide_drive_t *drive, int arg) | |||
1186 | return 0; | 969 | return 0; |
1187 | } | 970 | } |
1188 | 971 | ||
1189 | static int set_xfer_rate (ide_drive_t *drive, int arg) | ||
1190 | { | ||
1191 | int err; | ||
1192 | |||
1193 | if (arg < 0 || arg > 70) | ||
1194 | return -EINVAL; | ||
1195 | |||
1196 | err = ide_wait_cmd(drive, | ||
1197 | WIN_SETFEATURES, (u8) arg, | ||
1198 | SETFEATURES_XFER, 0, NULL); | ||
1199 | |||
1200 | if (!err && arg) { | ||
1201 | ide_set_xfer_rate(drive, (u8) arg); | ||
1202 | ide_driveid_update(drive); | ||
1203 | } | ||
1204 | return err; | ||
1205 | } | ||
1206 | |||
1207 | /** | ||
1208 | * ide_add_generic_settings - generic ide settings | ||
1209 | * @drive: drive being configured | ||
1210 | * | ||
1211 | * Add the generic parts of the system settings to the /proc files. | ||
1212 | * The caller must not be holding the ide_setting_sem. | ||
1213 | */ | ||
1214 | |||
1215 | void ide_add_generic_settings (ide_drive_t *drive) | ||
1216 | { | ||
1217 | /* | ||
1218 | * drive setting name read/write access data type min max mul_factor div_factor data pointer set function | ||
1219 | */ | ||
1220 | __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); | ||
1221 | __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); | ||
1222 | __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); | ||
1223 | __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); | ||
1224 | __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); | ||
1225 | __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); | ||
1226 | __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); | ||
1227 | __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); | ||
1228 | __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); | ||
1229 | } | ||
1230 | |||
1231 | /** | 972 | /** |
1232 | * system_bus_clock - clock guess | 973 | * system_bus_clock - clock guess |
1233 | * | 974 | * |
@@ -1922,54 +1663,6 @@ static void __init probe_for_hwifs (void) | |||
1922 | #endif | 1663 | #endif |
1923 | } | 1664 | } |
1924 | 1665 | ||
1925 | void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) | ||
1926 | { | ||
1927 | #ifdef CONFIG_IDE_PROC_FS | ||
1928 | ide_add_proc_entries(drive->proc, driver->proc, drive); | ||
1929 | #endif | ||
1930 | } | ||
1931 | |||
1932 | EXPORT_SYMBOL(ide_register_subdriver); | ||
1933 | |||
1934 | /** | ||
1935 | * ide_unregister_subdriver - disconnect drive from driver | ||
1936 | * @drive: drive to unplug | ||
1937 | * @driver: driver | ||
1938 | * | ||
1939 | * Disconnect a drive from the driver it was attached to and then | ||
1940 | * clean up the various proc files and other objects attached to it. | ||
1941 | * | ||
1942 | * Takes ide_setting_sem and ide_lock. | ||
1943 | * Caller must hold none of the locks. | ||
1944 | */ | ||
1945 | |||
1946 | void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) | ||
1947 | { | ||
1948 | unsigned long flags; | ||
1949 | |||
1950 | #ifdef CONFIG_IDE_PROC_FS | ||
1951 | ide_remove_proc_entries(drive->proc, driver->proc); | ||
1952 | #endif | ||
1953 | down(&ide_setting_sem); | ||
1954 | spin_lock_irqsave(&ide_lock, flags); | ||
1955 | /* | ||
1956 | * ide_setting_sem protects the settings list | ||
1957 | * ide_lock protects the use of settings | ||
1958 | * | ||
1959 | * so we need to hold both, ide_settings_sem because we want to | ||
1960 | * modify the settings list, and ide_lock because we cannot take | ||
1961 | * a setting out that is being used. | ||
1962 | * | ||
1963 | * OTOH both ide_{read,write}_setting are only ever used under | ||
1964 | * ide_setting_sem. | ||
1965 | */ | ||
1966 | auto_remove_settings(drive); | ||
1967 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1968 | up(&ide_setting_sem); | ||
1969 | } | ||
1970 | |||
1971 | EXPORT_SYMBOL(ide_unregister_subdriver); | ||
1972 | |||
1973 | /* | 1666 | /* |
1974 | * Probe module | 1667 | * Probe module |
1975 | */ | 1668 | */ |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 4388b8ab69a1..8263f752809d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -721,6 +721,7 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r | |||
721 | return ide_stopped; | 721 | return ide_stopped; |
722 | } | 722 | } |
723 | 723 | ||
724 | #ifdef CONFIG_IDE_PROC_FS | ||
724 | static void idescsi_add_settings(ide_drive_t *drive) | 725 | static void idescsi_add_settings(ide_drive_t *drive) |
725 | { | 726 | { |
726 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | 727 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); |
@@ -734,6 +735,9 @@ static void idescsi_add_settings(ide_drive_t *drive) | |||
734 | ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); | 735 | ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); |
735 | ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); | 736 | ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); |
736 | } | 737 | } |
738 | #else | ||
739 | static inline void idescsi_add_settings(ide_drive_t *drive) { ; } | ||
740 | #endif | ||
737 | 741 | ||
738 | /* | 742 | /* |
739 | * Driver initialization. | 743 | * Driver initialization. |
@@ -756,7 +760,7 @@ static void ide_scsi_remove(ide_drive_t *drive) | |||
756 | struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); | 760 | struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); |
757 | struct gendisk *g = scsi->disk; | 761 | struct gendisk *g = scsi->disk; |
758 | 762 | ||
759 | ide_unregister_subdriver(drive, scsi->driver); | 763 | ide_proc_unregister_driver(drive, scsi->driver); |
760 | 764 | ||
761 | ide_unregister_region(g); | 765 | ide_unregister_region(g); |
762 | 766 | ||
@@ -775,8 +779,6 @@ static ide_proc_entry_t idescsi_proc[] = { | |||
775 | { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, | 779 | { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, |
776 | { NULL, 0, NULL, NULL } | 780 | { NULL, 0, NULL, NULL } |
777 | }; | 781 | }; |
778 | #else | ||
779 | # define idescsi_proc NULL | ||
780 | #endif | 782 | #endif |
781 | 783 | ||
782 | static ide_driver_t idescsi_driver = { | 784 | static ide_driver_t idescsi_driver = { |
@@ -790,11 +792,13 @@ static ide_driver_t idescsi_driver = { | |||
790 | .version = IDESCSI_VERSION, | 792 | .version = IDESCSI_VERSION, |
791 | .media = ide_scsi, | 793 | .media = ide_scsi, |
792 | .supports_dsc_overlap = 0, | 794 | .supports_dsc_overlap = 0, |
793 | .proc = idescsi_proc, | ||
794 | .do_request = idescsi_do_request, | 795 | .do_request = idescsi_do_request, |
795 | .end_request = idescsi_end_request, | 796 | .end_request = idescsi_end_request, |
796 | .error = idescsi_atapi_error, | 797 | .error = idescsi_atapi_error, |
797 | .abort = idescsi_atapi_abort, | 798 | .abort = idescsi_atapi_abort, |
799 | #ifdef CONFIG_IDE_PROC_FS | ||
800 | .proc = idescsi_proc, | ||
801 | #endif | ||
798 | }; | 802 | }; |
799 | 803 | ||
800 | static int idescsi_ide_open(struct inode *inode, struct file *filp) | 804 | static int idescsi_ide_open(struct inode *inode, struct file *filp) |
@@ -1153,7 +1157,7 @@ static int ide_scsi_probe(ide_drive_t *drive) | |||
1153 | idescsi->host = host; | 1157 | idescsi->host = host; |
1154 | idescsi->disk = g; | 1158 | idescsi->disk = g; |
1155 | g->private_data = &idescsi->driver; | 1159 | g->private_data = &idescsi->driver; |
1156 | ide_register_subdriver(drive, &idescsi_driver); | 1160 | ide_proc_register_driver(drive, &idescsi_driver); |
1157 | err = 0; | 1161 | err = 0; |
1158 | idescsi_setup(drive, idescsi); | 1162 | idescsi_setup(drive, idescsi); |
1159 | g->fops = &idescsi_ops; | 1163 | g->fops = &idescsi_ops; |
@@ -1165,7 +1169,7 @@ static int ide_scsi_probe(ide_drive_t *drive) | |||
1165 | } | 1169 | } |
1166 | /* fall through on error */ | 1170 | /* fall through on error */ |
1167 | ide_unregister_region(g); | 1171 | ide_unregister_region(g); |
1168 | ide_unregister_subdriver(drive, &idescsi_driver); | 1172 | ide_proc_unregister_driver(drive, &idescsi_driver); |
1169 | 1173 | ||
1170 | put_disk(g); | 1174 | put_disk(g); |
1171 | out_host_put: | 1175 | out_host_put: |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 591a0b55e31c..477b8c6be727 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -559,9 +559,10 @@ typedef struct ide_drive_s { | |||
559 | struct ide_drive_s *next; /* circular list of hwgroup drives */ | 559 | struct ide_drive_s *next; /* circular list of hwgroup drives */ |
560 | void *driver_data; /* extra driver data */ | 560 | void *driver_data; /* extra driver data */ |
561 | struct hd_driveid *id; /* drive model identification info */ | 561 | struct hd_driveid *id; /* drive model identification info */ |
562 | #ifdef CONFIG_IDE_PROC_FS | ||
562 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ | 563 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ |
563 | struct ide_settings_s *settings;/* /proc/ide/ drive settings */ | 564 | struct ide_settings_s *settings;/* /proc/ide/ drive settings */ |
564 | 565 | #endif | |
565 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ | 566 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ |
566 | 567 | ||
567 | unsigned long sleep; /* sleep until this time */ | 568 | unsigned long sleep; /* sleep until this time */ |
@@ -858,8 +859,15 @@ typedef struct hwgroup_s { | |||
858 | unsigned char cmd_buf[4]; | 859 | unsigned char cmd_buf[4]; |
859 | } ide_hwgroup_t; | 860 | } ide_hwgroup_t; |
860 | 861 | ||
861 | /* structure attached to the request for IDE_TASK_CMDS */ | 862 | typedef struct ide_driver_s ide_driver_t; |
863 | |||
864 | extern struct semaphore ide_setting_sem; | ||
862 | 865 | ||
866 | int set_io_32bit(ide_drive_t *, int); | ||
867 | int set_pio_mode(ide_drive_t *, int); | ||
868 | int set_using_dma(ide_drive_t *, int); | ||
869 | |||
870 | #ifdef CONFIG_IDE_PROC_FS | ||
863 | /* | 871 | /* |
864 | * configurable drive settings | 872 | * configurable drive settings |
865 | */ | 873 | */ |
@@ -887,12 +895,7 @@ typedef struct ide_settings_s { | |||
887 | struct ide_settings_s *next; | 895 | struct ide_settings_s *next; |
888 | } ide_settings_t; | 896 | } ide_settings_t; |
889 | 897 | ||
890 | extern struct semaphore ide_setting_sem; | ||
891 | int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); | 898 | int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); |
892 | extern ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name); | ||
893 | extern int ide_read_setting(ide_drive_t *t, ide_settings_t *setting); | ||
894 | extern int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val); | ||
895 | extern void ide_add_generic_settings(ide_drive_t *drive); | ||
896 | 899 | ||
897 | /* | 900 | /* |
898 | * /proc/ide interface | 901 | * /proc/ide interface |
@@ -904,15 +907,17 @@ typedef struct { | |||
904 | write_proc_t *write_proc; | 907 | write_proc_t *write_proc; |
905 | } ide_proc_entry_t; | 908 | } ide_proc_entry_t; |
906 | 909 | ||
907 | #ifdef CONFIG_IDE_PROC_FS | ||
908 | extern struct proc_dir_entry *proc_ide_root; | 910 | extern struct proc_dir_entry *proc_ide_root; |
909 | 911 | ||
910 | void proc_ide_create(void); | 912 | void proc_ide_create(void); |
911 | void proc_ide_destroy(void); | 913 | void proc_ide_destroy(void); |
912 | void create_proc_ide_interfaces(void); | 914 | void create_proc_ide_interfaces(void); |
913 | void destroy_proc_ide_interface(ide_hwif_t *); | 915 | void destroy_proc_ide_interface(ide_hwif_t *); |
914 | void ide_add_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *, void *); | 916 | void ide_proc_register_driver(ide_drive_t *, ide_driver_t *); |
915 | void ide_remove_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *); | 917 | void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *); |
918 | |||
919 | void ide_add_generic_settings(ide_drive_t *); | ||
920 | |||
916 | read_proc_t proc_ide_read_capacity; | 921 | read_proc_t proc_ide_read_capacity; |
917 | read_proc_t proc_ide_read_geometry; | 922 | read_proc_t proc_ide_read_geometry; |
918 | 923 | ||
@@ -940,6 +945,9 @@ static inline void proc_ide_create(void) { ; } | |||
940 | static inline void proc_ide_destroy(void) { ; } | 945 | static inline void proc_ide_destroy(void) { ; } |
941 | static inline void create_proc_ide_interfaces(void) { ; } | 946 | static inline void create_proc_ide_interfaces(void) { ; } |
942 | static inline void destroy_proc_ide_interface(ide_hwif_t *hwif) { ; } | 947 | static inline void destroy_proc_ide_interface(ide_hwif_t *hwif) { ; } |
948 | static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } | ||
949 | static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } | ||
950 | static inline void ide_add_generic_settings(ide_drive_t *drive) { ; } | ||
943 | #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; | 951 | #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; |
944 | #endif | 952 | #endif |
945 | 953 | ||
@@ -982,7 +990,7 @@ enum { | |||
982 | * The gendriver.owner field should be set to the module owner of this driver. | 990 | * The gendriver.owner field should be set to the module owner of this driver. |
983 | * The gendriver.name field should be set to the name of this driver | 991 | * The gendriver.name field should be set to the name of this driver |
984 | */ | 992 | */ |
985 | typedef struct ide_driver_s { | 993 | struct ide_driver_s { |
986 | const char *version; | 994 | const char *version; |
987 | u8 media; | 995 | u8 media; |
988 | unsigned supports_dsc_overlap : 1; | 996 | unsigned supports_dsc_overlap : 1; |
@@ -990,12 +998,14 @@ typedef struct ide_driver_s { | |||
990 | int (*end_request)(ide_drive_t *, int, int); | 998 | int (*end_request)(ide_drive_t *, int, int); |
991 | ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); | 999 | ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); |
992 | ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); | 1000 | ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); |
993 | ide_proc_entry_t *proc; | ||
994 | struct device_driver gen_driver; | 1001 | struct device_driver gen_driver; |
995 | int (*probe)(ide_drive_t *); | 1002 | int (*probe)(ide_drive_t *); |
996 | void (*remove)(ide_drive_t *); | 1003 | void (*remove)(ide_drive_t *); |
997 | void (*shutdown)(ide_drive_t *); | 1004 | void (*shutdown)(ide_drive_t *); |
998 | } ide_driver_t; | 1005 | #ifdef CONFIG_IDE_PROC_FS |
1006 | ide_proc_entry_t *proc; | ||
1007 | #endif | ||
1008 | }; | ||
999 | 1009 | ||
1000 | #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) | 1010 | #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) |
1001 | 1011 | ||
@@ -1205,9 +1215,6 @@ extern void default_hwif_iops(ide_hwif_t *); | |||
1205 | extern void default_hwif_mmiops(ide_hwif_t *); | 1215 | extern void default_hwif_mmiops(ide_hwif_t *); |
1206 | extern void default_hwif_transport(ide_hwif_t *); | 1216 | extern void default_hwif_transport(ide_hwif_t *); |
1207 | 1217 | ||
1208 | void ide_register_subdriver(ide_drive_t *, ide_driver_t *); | ||
1209 | void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *); | ||
1210 | |||
1211 | #define ON_BOARD 1 | 1218 | #define ON_BOARD 1 |
1212 | #define NEVER_BOARD 0 | 1219 | #define NEVER_BOARD 0 |
1213 | 1220 | ||