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 /drivers/ide/ide.c | |
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>
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 313 |
1 files changed, 3 insertions, 310 deletions
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 | */ |