diff options
Diffstat (limited to 'drivers/ide/ide-disk.c')
| -rw-r--r-- | drivers/ide/ide-disk.c | 101 |
1 files changed, 78 insertions, 23 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 37aa6ddd9702..7fff773f2df7 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -559,8 +559,7 @@ static sector_t idedisk_capacity (ide_drive_t *drive) | |||
| 559 | return drive->capacity64 - drive->sect0; | 559 | return drive->capacity64 - drive->sect0; |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | #ifdef CONFIG_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,12 +677,7 @@ 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 | 680 | #endif /* CONFIG_IDE_PROC_FS */ | |
| 682 | #else | ||
| 683 | |||
| 684 | #define idedisk_proc NULL | ||
| 685 | |||
| 686 | #endif /* CONFIG_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) |
| 689 | { | 683 | { |
| @@ -737,6 +731,9 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
| 737 | { | 731 | { |
| 738 | struct request rq; | 732 | struct request rq; |
| 739 | 733 | ||
| 734 | if (arg < 0 || arg > drive->id->max_multsect) | ||
| 735 | return -EINVAL; | ||
| 736 | |||
| 740 | if (drive->special.b.set_multmode) | 737 | if (drive->special.b.set_multmode) |
| 741 | return -EBUSY; | 738 | return -EBUSY; |
| 742 | ide_init_drive_cmd (&rq); | 739 | ide_init_drive_cmd (&rq); |
| @@ -749,6 +746,9 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
| 749 | 746 | ||
| 750 | static int set_nowerr(ide_drive_t *drive, int arg) | 747 | static int set_nowerr(ide_drive_t *drive, int arg) |
| 751 | { | 748 | { |
| 749 | if (arg < 0 || arg > 1) | ||
| 750 | return -EINVAL; | ||
| 751 | |||
| 752 | if (ide_spin_wait_hwgroup(drive)) | 752 | if (ide_spin_wait_hwgroup(drive)) |
| 753 | return -EBUSY; | 753 | return -EBUSY; |
| 754 | drive->nowerr = arg; | 754 | drive->nowerr = arg; |
| @@ -800,6 +800,9 @@ static int write_cache(ide_drive_t *drive, int arg) | |||
| 800 | ide_task_t args; | 800 | ide_task_t args; |
| 801 | int err = 1; | 801 | int err = 1; |
| 802 | 802 | ||
| 803 | if (arg < 0 || arg > 1) | ||
| 804 | return -EINVAL; | ||
| 805 | |||
| 803 | if (ide_id_has_flush_cache(drive->id)) { | 806 | if (ide_id_has_flush_cache(drive->id)) { |
| 804 | memset(&args, 0, sizeof(ide_task_t)); | 807 | memset(&args, 0, sizeof(ide_task_t)); |
| 805 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? | 808 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? |
| @@ -835,6 +838,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) | |||
| 835 | { | 838 | { |
| 836 | ide_task_t args; | 839 | ide_task_t args; |
| 837 | 840 | ||
| 841 | if (arg < 0 || arg > 254) | ||
| 842 | return -EINVAL; | ||
| 843 | |||
| 838 | memset(&args, 0, sizeof(ide_task_t)); | 844 | memset(&args, 0, sizeof(ide_task_t)); |
| 839 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : | 845 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : |
| 840 | SETFEATURES_DIS_AAM; | 846 | SETFEATURES_DIS_AAM; |
| @@ -855,6 +861,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) | |||
| 855 | */ | 861 | */ |
| 856 | static int set_lba_addressing(ide_drive_t *drive, int arg) | 862 | static int set_lba_addressing(ide_drive_t *drive, int arg) |
| 857 | { | 863 | { |
| 864 | if (arg < 0 || arg > 2) | ||
| 865 | return -EINVAL; | ||
| 866 | |||
| 858 | drive->addressing = 0; | 867 | drive->addressing = 0; |
| 859 | 868 | ||
| 860 | if (HWIF(drive)->no_lba48) | 869 | if (HWIF(drive)->no_lba48) |
| @@ -866,23 +875,27 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) | |||
| 866 | return 0; | 875 | return 0; |
| 867 | } | 876 | } |
| 868 | 877 | ||
| 878 | #ifdef CONFIG_IDE_PROC_FS | ||
| 869 | static void idedisk_add_settings(ide_drive_t *drive) | 879 | static void idedisk_add_settings(ide_drive_t *drive) |
| 870 | { | 880 | { |
| 871 | struct hd_driveid *id = drive->id; | 881 | struct hd_driveid *id = drive->id; |
| 872 | 882 | ||
| 873 | ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); | 883 | ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); |
| 874 | ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); | 884 | ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); |
| 875 | ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); | 885 | ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); |
| 876 | ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); | 886 | ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); |
| 877 | ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); | 887 | ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); |
| 878 | ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); | 888 | ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); |
| 879 | ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); | 889 | ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); |
| 880 | ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); | 890 | ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); |
| 881 | ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); | 891 | ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); |
| 882 | ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); | 892 | ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); |
| 883 | ide_add_setting(drive, "failures", SETTING_RW, -1, -1, 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); |
| 884 | ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, 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); |
| 885 | } | 895 | } |
| 896 | #else | ||
| 897 | static inline void idedisk_add_settings(ide_drive_t *drive) { ; } | ||
| 898 | #endif | ||
| 886 | 899 | ||
| 887 | static void idedisk_setup (ide_drive_t *drive) | 900 | static void idedisk_setup (ide_drive_t *drive) |
| 888 | { | 901 | { |
| @@ -1001,7 +1014,7 @@ static void ide_disk_remove(ide_drive_t *drive) | |||
| 1001 | struct ide_disk_obj *idkp = drive->driver_data; | 1014 | struct ide_disk_obj *idkp = drive->driver_data; |
| 1002 | struct gendisk *g = idkp->disk; | 1015 | struct gendisk *g = idkp->disk; |
| 1003 | 1016 | ||
| 1004 | ide_unregister_subdriver(drive, idkp->driver); | 1017 | ide_proc_unregister_driver(drive, idkp->driver); |
| 1005 | 1018 | ||
| 1006 | del_gendisk(g); | 1019 | del_gendisk(g); |
| 1007 | 1020 | ||
| @@ -1066,7 +1079,9 @@ static ide_driver_t idedisk_driver = { | |||
| 1066 | .end_request = ide_end_request, | 1079 | .end_request = ide_end_request, |
| 1067 | .error = __ide_error, | 1080 | .error = __ide_error, |
| 1068 | .abort = __ide_abort, | 1081 | .abort = __ide_abort, |
| 1082 | #ifdef CONFIG_IDE_PROC_FS | ||
| 1069 | .proc = idedisk_proc, | 1083 | .proc = idedisk_proc, |
| 1084 | #endif | ||
| 1070 | }; | 1085 | }; |
| 1071 | 1086 | ||
| 1072 | static int idedisk_open(struct inode *inode, struct file *filp) | 1087 | static int idedisk_open(struct inode *inode, struct file *filp) |
| @@ -1140,9 +1155,49 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
| 1140 | static int idedisk_ioctl(struct inode *inode, struct file *file, | 1155 | static int idedisk_ioctl(struct inode *inode, struct file *file, |
| 1141 | unsigned int cmd, unsigned long arg) | 1156 | unsigned int cmd, unsigned long arg) |
| 1142 | { | 1157 | { |
| 1158 | unsigned long flags; | ||
| 1143 | struct block_device *bdev = inode->i_bdev; | 1159 | struct block_device *bdev = inode->i_bdev; |
| 1144 | struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); | 1160 | struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); |
| 1145 | return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); | 1161 | ide_drive_t *drive = idkp->drive; |
| 1162 | int err, (*setfunc)(ide_drive_t *, int); | ||
| 1163 | u8 *val; | ||
| 1164 | |||
| 1165 | switch (cmd) { | ||
| 1166 | case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; | ||
| 1167 | case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; | ||
| 1168 | case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; | ||
| 1169 | case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; | ||
| 1170 | case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; | ||
| 1171 | case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; | ||
| 1172 | case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; | ||
| 1173 | case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; | ||
| 1174 | case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; | ||
| 1175 | case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | return generic_ide_ioctl(drive, file, bdev, cmd, arg); | ||
| 1179 | |||
| 1180 | read_val: | ||
| 1181 | down(&ide_setting_sem); | ||
| 1182 | spin_lock_irqsave(&ide_lock, flags); | ||
| 1183 | err = *val; | ||
| 1184 | spin_unlock_irqrestore(&ide_lock, flags); | ||
| 1185 | up(&ide_setting_sem); | ||
| 1186 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | ||
| 1187 | |||
| 1188 | set_val: | ||
| 1189 | if (bdev != bdev->bd_contains) | ||
| 1190 | err = -EINVAL; | ||
| 1191 | else { | ||
| 1192 | if (!capable(CAP_SYS_ADMIN)) | ||
| 1193 | err = -EACCES; | ||
| 1194 | else { | ||
| 1195 | down(&ide_setting_sem); | ||
| 1196 | err = setfunc(drive, arg); | ||
| 1197 | up(&ide_setting_sem); | ||
| 1198 | } | ||
| 1199 | } | ||
| 1200 | return err; | ||
| 1146 | } | 1201 | } |
| 1147 | 1202 | ||
| 1148 | static int idedisk_media_changed(struct gendisk *disk) | 1203 | static int idedisk_media_changed(struct gendisk *disk) |
| @@ -1202,7 +1257,7 @@ static int ide_disk_probe(ide_drive_t *drive) | |||
| 1202 | 1257 | ||
| 1203 | ide_init_disk(g, drive); | 1258 | ide_init_disk(g, drive); |
| 1204 | 1259 | ||
| 1205 | ide_register_subdriver(drive, &idedisk_driver); | 1260 | ide_proc_register_driver(drive, &idedisk_driver); |
| 1206 | 1261 | ||
| 1207 | kref_init(&idkp->kref); | 1262 | kref_init(&idkp->kref); |
| 1208 | 1263 | ||
