/* SPDX-License-Identifier: GPL-2.0+ */ #ifndef _AVM_HELPERS_H_ #include #include #include #include #define LINUX_STABLE_VERSION_HAS_SUBLEVEL(a, b, c) \ (LINUX_VERSION_CODE < KERNEL_VERSION(a, (b) + 1, 0) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(a, b, c)) /* Return: * < 0: Error (-EIO, -EPERM, -EINVAL) * = 0: Empty file * > 0: Number of bytes read */ int avm_read_from_file(const char *filename, char *str, int maxlen); /* Return: * < 0: Error (-EIO, -EPERM, -EINVAL) * = 0: Success */ int avm_write_to_file(const char *filename, const char *str, int len); /** * register_simple_dma_device - Register a simple (dummy) device for DMA * @dev: The device to register * @name: Device name * * Register a simple device that can be used for DMA. AVM drivers that do not * follow the Linux driver model but need to do DMA can hereby acquire a * dummy device that satisfies the requirements of the DMA API. * * There is no parent device or bus that the device is attached to. The * dma_mask of the device ist unlimited. * * All fields in @dev that have no explicit value must be initialized by the * caller to 0. */ int register_simple_dma_device(struct device *dev, const char *name); void unregister_simple_dma_device(struct device *dev); #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) static inline time64_t __ktime_get_real_seconds(void) { return get_seconds(); } #endif /* On old kernels that don't have it, we emulate ktime_get_seconds. */ time64_t ktime_get_seconds(void); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) #define rtc_time64_to_tm(a, b) rtc_time_to_tm(a, b) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) typedef void (*timer_func_t)(unsigned long); #ifndef from_timer #define from_timer(var, callback_timer, timer_fieldname) \ container_of(callback_timer, typeof(*var), timer_fieldname) #endif #ifndef timer_setup #ifndef __setup_timer /* Ancient kernels << v3.7 (puma6...), no support for timer flags */ # define __setup_timer(_timer, _fn, _data, _flags) \ do { \ BUILD_BUG_ON(_flags); \ setup_timer((_timer), (_fn), (_data)); \ } while (0) #endif /* * Unfortunately, some AVM kernel sub-projects (telephony...) enable * -Wextra, which implies -Wcast-function-type for gcc >= v8 */ #pragma GCC push_options #if __GNUC__ >= 8 # pragma GCC diagnostic ignored "-Wcast-function-type" #endif #define timer_setup timer_setup static inline void timer_setup(struct timer_list *timer, void (*func)(struct timer_list *), unsigned int flags) { __setup_timer(timer, (timer_func_t)func, (unsigned long)timer, flags); } #pragma GCC pop_options #endif /* timer_setup */ #else /* KERNEL_VERSION */ typedef void (*timer_func_t)(struct timer_list *); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) /* * Upstream has re-ordered the arguments of kernel_read and kernel_write, and * made the loff_t arg a pointer. Provide avm_* wrappers that use the new * signature. */ #define avm_kernel_read(file, buf, count, poff) kernel_read(file, *(poff), buf, count) #define avm_kernel_write(file, buf, count, poff) kernel_write(file, buf, count, *(poff)) #else #define avm_kernel_read kernel_read #define avm_kernel_write kernel_write #endif ssize_t time_to_ascii(time64_t local_time, char *buf, int len); #ifndef fallthrough /* Linux << v5.4 */ #if __has_attribute(__fallthrough__) # define fallthrough __attribute__((__fallthrough__)) #else # define fallthrough do {} while (0) /* fallthrough */ #endif #endif /* fallthrough */ #ifndef __ro_after_init /* Linux << v4.6 */ #define __ro_after_init #endif #define _AVM_HELPERS_H_ #endif /* _AVM_HELPERS_H */