Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

comedi: add comedi_check_request_region()

There is an existing comedi_request_region(dev, start, len) function
used by COMEDI drivers for legacy devices to request an I/O port region
starting at a specified base address (which must be non-zero) and with a
specified length. It uses request_region(). On success, it sets
dev->iobase and dev->iolen and returns 0. There is a alternative
function __comedi_request_region(dev, start, len) which does the same
thing without setting dev->iobase and dev->iolen.

Most hardware devices have restrictions on the allowed I/O port base
address and alignment, so add new functions
comedi_check_request_region(dev, start, len, minstart, maxend, minalign)
and __comedi_check_request_region(dev, start, len, minstart, maxend,
minalign) to perform these additional checks. Turn the original
functions into static inline wrapper functions that call the new
functions.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260130170416.49994-2-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ian Abbott and committed by
Greg Kroah-Hartman
241cb8de 8f348102

+84 -15
+35 -11
drivers/comedi/drivers.c
··· 933 933 EXPORT_SYMBOL_GPL(comedi_load_firmware); 934 934 935 935 /** 936 - * __comedi_request_region() - Request an I/O region for a legacy driver 936 + * __comedi_check_request_region() - Request an I/O region for a legacy driver 937 937 * @dev: COMEDI device. 938 938 * @start: Base address of the I/O region. 939 939 * @len: Length of the I/O region. 940 + * @minstart: Minimum allowed start address of region. 941 + * @maxend: Maximum allowed region end address of region. 942 + * @minalign: Required alignment for base address. 940 943 * 941 944 * Requests the specified I/O port region which must start at a non-zero 942 - * address. 945 + * address, must fall within specified bounds, and must be correctly aligned. 943 946 * 944 947 * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request 945 948 * fails. 946 949 */ 947 - int __comedi_request_region(struct comedi_device *dev, 948 - unsigned long start, unsigned long len) 950 + int __comedi_check_request_region(struct comedi_device *dev, 951 + unsigned long start, unsigned long len, 952 + unsigned long minstart, unsigned long maxend, 953 + unsigned long minalign) 949 954 { 950 955 if (!start) { 951 956 dev_warn(dev->class_dev, 952 957 "%s: a I/O base address must be specified\n", 958 + dev->board_name); 959 + return -EINVAL; 960 + } 961 + 962 + if (start < minstart || start > maxend || maxend - start < len - 1) { 963 + dev_warn(dev->class_dev, 964 + "%s: I/O base address or length out of range\n", 965 + dev->board_name); 966 + return -EINVAL; 967 + } 968 + if (!IS_ALIGNED(start, minalign)) { 969 + dev_warn(dev->class_dev, 970 + "%s: I/O base address not correctly aligned\n", 953 971 dev->board_name); 954 972 return -EINVAL; 955 973 } ··· 980 962 981 963 return 0; 982 964 } 983 - EXPORT_SYMBOL_GPL(__comedi_request_region); 965 + EXPORT_SYMBOL_GPL(__comedi_check_request_region); 984 966 985 967 /** 986 - * comedi_request_region() - Request an I/O region for a legacy driver 968 + * comedi_check_request_region() - Request an I/O region for a legacy driver 987 969 * @dev: COMEDI device. 988 970 * @start: Base address of the I/O region. 989 971 * @len: Length of the I/O region. 972 + * @minstart: Minimum allowed start address of region. 973 + * @maxend: Maximum allowed region end address of region. 974 + * @minalign: Required alignment for base address. 990 975 * 991 976 * Requests the specified I/O port region which must start at a non-zero 992 - * address. 977 + * address, must fall within specified bounds, and must be correctly aligned. 993 978 * 994 979 * On success, @dev->iobase is set to the base address of the region and 995 980 * @dev->iolen is set to its length. ··· 1000 979 * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request 1001 980 * fails. 1002 981 */ 1003 - int comedi_request_region(struct comedi_device *dev, 1004 - unsigned long start, unsigned long len) 982 + int comedi_check_request_region(struct comedi_device *dev, 983 + unsigned long start, unsigned long len, 984 + unsigned long minstart, unsigned long maxend, 985 + unsigned long minalign) 1005 986 { 1006 987 int ret; 1007 988 1008 - ret = __comedi_request_region(dev, start, len); 989 + ret = __comedi_check_request_region(dev, start, len, minstart, maxend, 990 + minalign); 1009 991 if (ret == 0) { 1010 992 dev->iobase = start; 1011 993 dev->iolen = len; ··· 1016 992 1017 993 return ret; 1018 994 } 1019 - EXPORT_SYMBOL_GPL(comedi_request_region); 995 + EXPORT_SYMBOL_GPL(comedi_check_request_region); 1020 996 1021 997 /** 1022 998 * comedi_legacy_detach() - A generic (*detach) function for legacy drivers
+49 -4
include/linux/comedi/comedidev.h
··· 1026 1026 unsigned long context), 1027 1027 unsigned long context); 1028 1028 1029 - int __comedi_request_region(struct comedi_device *dev, 1030 - unsigned long start, unsigned long len); 1031 - int comedi_request_region(struct comedi_device *dev, 1032 - unsigned long start, unsigned long len); 1029 + int __comedi_check_request_region(struct comedi_device *dev, 1030 + unsigned long start, unsigned long len, 1031 + unsigned long minstart, unsigned long maxend, 1032 + unsigned long minalign); 1033 + int comedi_check_request_region(struct comedi_device *dev, 1034 + unsigned long start, unsigned long len, 1035 + unsigned long minstart, unsigned long maxend, 1036 + unsigned long minalign); 1037 + 1038 + /** 1039 + * __comedi_request_region() - Request an I/O region for a legacy driver 1040 + * @dev: COMEDI device. 1041 + * @start: Base address of the I/O region. 1042 + * @len: Length of the I/O region. 1043 + * 1044 + * Requests the specified I/O port region which must start at a non-zero 1045 + * address. 1046 + * 1047 + * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request 1048 + * fails. 1049 + */ 1050 + static inline int __comedi_request_region(struct comedi_device *dev, 1051 + unsigned long start, 1052 + unsigned long len) 1053 + { 1054 + return __comedi_check_request_region(dev, start, len, 0, ~0ul, 1); 1055 + } 1056 + 1057 + /** 1058 + * comedi_request_region() - Request an I/O region for a legacy driver 1059 + * @dev: COMEDI device. 1060 + * @start: Base address of the I/O region. 1061 + * @len: Length of the I/O region. 1062 + * 1063 + * Requests the specified I/O port region which must start at a non-zero 1064 + * address. 1065 + * 1066 + * On success, @dev->iobase is set to the base address of the region and 1067 + * @dev->iolen is set to its length. 1068 + * 1069 + * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request 1070 + * fails. 1071 + */ 1072 + static inline int comedi_request_region(struct comedi_device *dev, 1073 + unsigned long start, unsigned long len) 1074 + { 1075 + return comedi_check_request_region(dev, start, len, 0, ~0ul, 1); 1076 + } 1077 + 1033 1078 void comedi_legacy_detach(struct comedi_device *dev); 1034 1079 1035 1080 int comedi_auto_config(struct device *hardware_device,